Codeforces Round #399 B 思维 C 模拟 D 概率dp E SG博弈
Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined)
B. Code For 1
题意:数n,不断拆分为 n/2, n&1, n/2,直到都为0或1。求区间[l, r]有多少个1。
tags:画一画很容易看出来,类似dfs中序遍历。
//#399 B #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a;i<=b;i++) #define per(i,b,a) for (int i=b;i>=a;i--) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f typedef long long ll; const int N = 2e5+10; ll get(ll n) { if(n<2) return 1; return (get(n>>1))*2+1; } ll solve(ll n, ll l, ll r) { if(n<2) return n; ll sz=get(n>>1), ans=0; if(l<=sz) ans+=solve(n>>1, l, min(r,sz)); if(l<=sz+1 && sz+1<=r) ans+=(n&1); if(sz+1<r) ans+=solve(n>>1, max(l-(sz+1),0LL), r-(sz+1)); // -(sz+1)有点巧妙 return ans; } int main() { ll n, l, r; cin>>n>>l>>r; cout<<solve(n, l, r)<<endl; return 0; }
C. Jon Snow and his Favourite Number
题意:数列a[],操作:将a[]从小到大排序,选取所有标号为奇数的数,使其异或 x。执行 k次,求最后数列中最大和最小的数值。
tags:仔细看题,关键是 a[i]<=1e3。所在对于所在可能出现的数都用数组搞出来就好。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a;i<=b;i++) #define per(i,b,a) for (int i=b;i>=a;i--) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f typedef long long ll; const int N = 1e5+10, M=1024; int a[N], cnt[N], n, k, x; int main() { scanf("%d %d %d", &n, &k, &x); int ai; rep(i,1,n) { scanf("%d", &ai); a[ai]++; } rep(ca,1,k) { int tot=0, y; rep(i,0,M) { if(tot&1) cnt[i]=a[i]>>1; else cnt[i]=(a[i]+1)>>1; tot+=a[i]; } rep(i,0,M) a[i]-=cnt[i], a[i^x]+=cnt[i]; } per(i,M,0) if(a[i]) { printf("%d ", i); break; } rep(i,0,M) if(a[i]) { printf("%d\n", i); break; } return 0; }
题意:有k种球,每天随机生成一个球。任务:集齐k种球,每种球至少有一个。给出pi,要使得完成任务的概率不小于(pi-epx)/2000, epx=1e-7,求最少需要多少天。
tags:dp[n][x]为第n天集齐了x种球的概率,状态转移:dp[n][x]=dp[n-1][x]*(x/k) + dp[n-1][x-1]*(k-(x-1))/k。预处理出dp[][],最后看dp[i][k]>=(pi-epx)/2000, 1<= i <=N 。 天数N取到1e4绝对够了。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a;i<=b;i++) #define per(i,b,a) for (int i=b;i>=a;i--) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f typedef long long ll; const int N = 1e4+10, M = 1e3+10; const double epx = 1e-7; double dp[N][M]; int main() { int k, q, p; scanf("%d %d", &k, &q); dp[0][0]=1; rep(i,1,N-1) rep(j,1,k) { dp[i][j]=dp[i-1][j]*j/k + dp[i-1][j-1]*(k-(j-1))/k; } while(q--) { scanf("%d", &p); rep(i,1,N-1) { if(dp[i][k]>=(p-epx)/2000) { printf("%d\n", i); break; } } } return 0; }
题意:n堆石子,两人轮流每次选一堆至少取走一个,最后不能取者败。限制:每一堆不能多次取同样多个石子,比如取走过 k 个,那这一堆就不能再取 k 个。问后手胜负。
tags:推出SG函数。但有个写法不明白。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a;i<=b;i++) #define per(i,b,a) for (int i=b;i>=a;i--) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define pb push_back typedef long long ll; const int N = 2e5+10; int main() { /* int n, si, ans=0; int sg[]={0 ,1 ,1 ,2 ,2 ,2 ,3 ,3 ,3 ,3 ,4 ,4 ,4 ,4 ,4 ,5 ,5 ,5 ,5 ,5 ,5 ,6 ,6 ,6 ,6 ,6 ,6 ,6 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,8 ,8 ,8 ,8 ,8 ,8 ,8 ,8 ,8 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,11 ,11 ,11 ,11 ,11 ,11 ,11 ,11 ,11 ,11 ,11 ,11 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,13 ,13 ,13 ,13 ,13 ,13 ,13 ,13 ,13 ,13 ,13 ,13 ,13 ,13 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,17 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 }; cin>>n; rep(ca,1,n) { cin>>si; ans^=sg[si]; } ans ? puts("NO") : puts("YES"); */ int n, ans=0, si; cin>>n; rep(ca,1,n) { cin>>si; ans^= ((int)sqrt(8*si+1)-1)/2; //不明白 } ans ? puts("NO") : puts("YES"); return 0; }