XTU Monthly, April 2014
阿新 • • 發佈:2019-01-31
題意:0通過+1,-1,*2操作得到n(10^18)的最小方案數
思路:倒著看,偶數必然由*2得到,奇數由+1或-1得到,開個map存一下算過的
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <map> using namespace std; typedef long long LL; map<LL,int>mp; LL solve(LL n){ if(mp[n]!=0) return mp[n]; if(n==0) return mp[n]=0; else if(n==1) return mp[n]=1; if(n&1) return mp[n]=min(solve(n+1),solve(n-1))+1; else return mp[n]=solve(n/2)+1; } int main(){ LL n; mp.clear(); while(scanf("%I64d",&n)!=EOF){ printf("%I64d\n",solve(n)); } return 0; }
B.Lucky Wheel
題意:轉盤1/2的概率無獎,1/8一等獎,1/8二等獎,1/8三等獎,1/8優秀獎,求x次一等獎,y次二等獎的期望
思路:用dp[i][j]表示i次一等獎,j次二等獎的期望
dp[i][j] = 1 + dp[i][j] * 3/4 + dp[i-1][j] * 1/8 + dp[i][j-1] * 1/8
dp[i][j] = 4 + (dp[i-1][j] + dp[i][j-1]) * 1/2
暴力處理一下就出來了
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <map> using namespace std; typedef long long LL; #define maxn 1010 double dp[maxn][maxn]; int main(){ for(int i=0;i<maxn;i++) dp[0][i]=8*i,dp[i][0]=8*i; for(int i=1;i<maxn;i++){ for(int j=1;j<maxn;j++) dp[i][j]=4.0+(dp[i-1][j]+dp[i][j-1])/2.0; } int x,y; while(scanf("%d%d",&x,&y)!=EOF){ printf("%.6lf\n",dp[x][y]); } return 0; }
C.A+B
題意:求只包含a,b數字的序列和為n的方案數
思路:擴充套件歐幾里得求出最小解的情況x0,y0,在保證都大於等於零的情況下,可以變換lcm(a,b)(即x0+=lcm(a,b)/b,y0-=lcm(a,b)/a)
所以總的方案數為 y0*b/lcm(a,b)+1 . a=b的時候特判
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <map> using namespace std; typedef long long LL; LL exgcd(LL a,LL b,LL &x,LL &y){ if(b==0){ x=1,y=0; return a; } else{ LL ans=exgcd(b,a%b,x,y); LL tmp=x; x=y; y=tmp-a/b*y; return ans; } } LL gcd(LL a,LL b){ if(b==0) return a; return gcd(b,a%b); } LL lcm(LL a,LL b){ return a/gcd(a,b)*b; } int main(){ LL a,b,x,y,c; while(scanf("%I64d%I64d%I64d",&a,&b,&c)!=EOF){ LL g=gcd(a,b); if(c%g!=0){ printf("0\n"); continue; } else if(a==b){ printf("%d\n",(c%a)==0 ); } else{ a/=g,b/=g,c/=g; exgcd(a,b,x,y); x*=c; x=(x%b+b)%b; a*=g,b*=g,c*=g; LL x0=x,y0=(c-a*x)/b; if(y0<0){ printf("0\n"); continue; } LL l=lcm(a,b); printf("%I64d\n",b*y0/l+1); } } return 0; }
D.Hexa Kill
題意:給出n個物品,m種限制,以及n個物品分別第幾個被選所消耗的能量,以及m對限制(x,y)表示x在y之後被選,求最小消耗
思路:喵似是圖論,不會
題意:有根樹每個節點有個權值,一開始都是0。 你有這麼兩種操作。
操作1: 你可以使某個節點加上一個值v(1≤v≤100),那麼這個節點的兒子就會加上2v,它兒子的兒子就加上3v...
操作2: 詢問一個節點的權值。
思路:線段樹。更新一個深度為d節點,它的兒子深度為dn,節點值為x+(dn-d+1)*v=x+dn*v-d*v+v,d*v是常數 ( by 小建建)
// by qqspeed
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
inline int input(){
int ret=0;bool isN=0;char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') isN=1;
c=getchar();
}
while(c>='0' && c<='9'){
ret=ret*10+c-'0';
c=getchar();
}
return isN?-ret:ret;
}
typedef long long ll;
#define N 100005
#define L t<<1
#define R t<<1|1
int t,n;
vector<int>e[N];
int op,x,y,q;
int cnt;
int to[N],rTo[N],r,dis[N],last[N];
inline void dfs(int now,int pre){
dis[now] = dis[pre]+1;
to[now]=cnt;
rTo[cnt]=now;
cnt++;
for(int i=0;i<e[now].size();i++){
dfs(e[now][i],now);
}
last[now]=cnt-1;
}
struct node{
int l,r;
ll v1,v2;
void init(int _l,int _r,ll _v1,ll _v2){
l=_l,r=_r;
v1=_v1,v2=_v2;
}
}root[N<<2];
inline void push_down(int t){
root[L].v1+=root[t].v1;
root[R].v1+=root[t].v1;
root[L].v2+=root[t].v2;
root[R].v2+=root[t].v2;
root[t].v1=root[t].v2=0;
}
inline void build(int t,int x,int y){
root[t].init(x,y,0,0);
if(x!=y){
int mid=(x+y)>>1;
build(L,x,mid),build(R,mid+1,y);
}
}
inline void Add(int t,int x,int y,ll v1,ll v2){
int l=root[t].l,r=root[t].r;
if(l==x && r==y){
root[t].v1+=v1;
root[t].v2+=v2;
return;
}
push_down(t);
int mid=(l+r)>>1;
if(y<=mid) Add(L,x,y,v1,v2);
else if(x>mid) Add(R,x,y,v1,v2);
else{
Add(L,x,mid,v1,v2);
Add(R,mid+1,y,v1,v2);
}
}
inline ll query(int t,int x){
int l=root[t].l,r=root[t].r;
if(l==r){
return root[t].v2+root[t].v1*dis[rTo[l]];
}
push_down(t);
int mid=(l+r)>>1;
if(x<=mid) return query(L,x);
else return query(R,x);
}
int main(){
t=input();
while(t--){
n=input();
for(int i=0;i<=n;i++) e[i].clear();
cnt=1;
for(int i=1;i<=n;i++){
x=input();
if(x==0) r=i;
else e[x].push_back(i);
}
dis[0]=0;
dfs(r,0);
build(1,1,cnt);
q=input();
while(q--){
op=input();
if(op==2){
x=input();
printf("%I64d\n",query(1,to[x]));
}
else{
x=input();
y=input();
ll v1=y;
ll v2=(1-dis[x])*y;
y=last[x];
x=to[x];
Add(1,x,y,v1,v2);
}
}
}
return 0;
}