https://ac.nowcoder.com/acm/contest/5671
Binary Vector(数学)
题意:求$frac{2^n-1}{2^n}$
代码来自:https://blog.nowcoder.net/n/1d9a191e486649fd8c7c62de021d322a?f=comment
#include<bits/stdc++.h> using namespace std; const long long mod=1e9+7; long long a[20000010],x=5e8+4,y=5e8+4; int main() { int n,t,i; a[1]=5e8+4; for(i=2;i<=2e7;i++) { x=x*y%mod; a[i]=(a[i-1]-a[i-1]*x)%mod+mod; } for(i=2;i<=2e7;i++) a[i]^=a[i-1]; scanf("%d",&t); while(t--) { scanf("%d",&n); printf("%lld ",a[n]); } return 0; }
解释:
K-Bag(DP)
题意:判断一个数组是不是K-Bag。K-Bag为由1~K的permutation的任意长度重复的子集。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+7; unordered_map<int,int>mp; ll a[N],f[N];//f:可能为断点的地方=1 int main(){ int t; scanf("%d",&t); while(t--){ mp.clear(); memset(f,0,sizeof(f)); int n;int k; scanf("%d%d",&n,&k); int flag=0,cnt=0; f[0]=1;//位置0可能是一个断点。 for(int i=1;i<=n;++i){ scanf("%d",&a[i]); if(a[i]>k) flag=1; } if(flag) {printf("NO ");continue;} for(int i=1;i<=n;++i){ if(i>k){ mp[a[i-k]]--; if(mp[a[i-k]]==0) cnt--; } if(mp[a[i]]==0) cnt++; mp[a[i]]++; if(cnt==k||cnt==i) f[i]=(i-k>0)?f[i-k]:1; /* 如果cnt==k,说明包括a[i]的前面k个数字满足一个k-bag 那么此时i是不是断点,取决于在这k个数字之前的几个区间 满不满足k-bag,所以转移掉 cnt==k必然有i-k>0 如果cnt==i,那么说明是有可能 不完整的最前面一段满足数字都不相等。 那么我们set此处为1,因为这里有成为断点的可能。 如果中间某处失败成为一个断点,那么此时不会赋值为1 那么这个原本可能是断点的位置的下一个位置就算成功也不会赋值1 所以到最后都满足要求的断点,只会在最后k个中出现 前面的即使=1也不算数 */ } mp.clear(); cnt=0; for(int i=n;i>=max(0,n-k);--i){ /* 只遍历最后一段,检查最后一段是否正确 */ if(cnt==n-i&&f[i]){flag=1;break;} if(mp[a[i]]==0) cnt++; mp[a[i]]++; } if(flag) printf("YES "); else printf("NO "); } }