Codeforces Round #166 (Div. 2)
p.s.这场比赛题目都还挺好的我觉得,但还是做跪了,要是没那4个hack的话就死了...
A.略
B.解法:可以直接预处理出来距离每个数最近的素数,然后加一遍。当然也可以打个素数表然后二分。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #define N 1000010 6 using namespace std; 7 bool p[N]; 8 int s[N]; 9 int x[1010][1010]; 10 int r[N],c[N]; 11 void init(){ 12 memset(p,1,sizeof(p)); 13 for(int i=2;i*i<N;i++) 14 for(int j=i;i*j<N;j++) 15 p[i*j]=0; 16 s[0]=0; 17 for(int i=2;i<N;i++) 18 if(p[i])s[++s[0]]=i; 19 } 20 int solve(int x){ 21 int pos=lower_bound(s+1,s+1+s[0],x)-s; 22 return s[pos]-x; 23 } 24 int main(){ 25 int n,m; 26 init(); 27 while(cin>>n>>m){ 28 memset(r,0,sizeof(r)); 29 memset(c,0,sizeof(c)); 30 for(int i=1;i<=n;i++){ 31 for(int j=1;j<=m;j++){ 32 cin>>x[i][j]; 33 r[i]+=solve(x[i][j]); 34 c[j]+=solve(x[i][j]); 35 } 36 } 37 int ans=1<<30; 38 for(int i=1;i<=n;i++)ans=min(ans,r[i]); 39 for(int j=1;j<=m;j++)ans=min(ans,c[j]); 40 cout<<ans<<endl; 41 } 42 return 0; 43 }
C.只要集合里的数不是等差数列就行了,我们可以每k个分个段,然后分配到各个集合,这样的话每个集合都是等差数列,我们把数列最后1或2项改一下就行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
D.构建字典树,一直向字典树中插入就行,O(n^2).貌似存在卡字符串哈希的算法,有待研究。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 1510 5 using namespace std; 6 char s[N]; 7 int x[26]; 8 int trie[N*N][26]; 9 int cnt,root; 10 int maxn; 11 int main(){ 12 while(~scanf("%s",s)){ 13 int n=strlen(s); 14 for(int i=0;i<26;i++){ 15 scanf("%1d",&x[i]); 16 x[i]^=1; 17 } 18 scanf("%d",&maxn); 19 memset(trie,-1,sizeof(trie)); 20 cnt=0; 21 int ans=0; 22 for(int i=0;i<n;i++){ 23 int p=0,num=0; 24 for(int j=i;j<n;j++){ 25 int id=s[j]-'a'; 26 num+=x[id]; 27 if(num>maxn){ 28 break; 29 } 30 if(trie[p][id]==-1){ 31 ans++; 32 trie[p][id]=++cnt; 33 } 34 p=trie[p][id]; 35 } 36 } 37 printf("%d\n",ans); 38 } 39 return 0; 40 }