这次考试CE了。
原因是我改了一个longlong没编译,然后最后查出来的时候已经没时间了。
不CE的话应该rk7左右。update:因为这个CE把我卡出了第一基房!!!!
但是都是暴力分。
T1:是一个规律题,给了5个样例,但我都没看出来,也是废了。我用背包A了
这个题首先是一道比较屎的背包都能想到。
但是转移会出错,原因在于:$f[j]|=f[(j-w[i]+k)%k]$这个东西转移顺序出问题了。
解决办法就是一个转移循环k次。
复杂度$O(nk^{2})$但是题目给了三个分档,k=100,k=1000,n,k=100000
首先100的肯定可以。
1000的就会出问题。但是有一个剪枝就是每次转移的时候转移完看看答案是否变化,如果不变化那么很显然就不用在循环接下来的保证正确性的k次循环。经过实测在100次左右答案就不在变化,复杂度可过。
100000的nk就死了,那么没办法,n的循环不能省,但是k的循环……,我可以随机找一个容积更新,大概随机次数在200次之后就稳定了。所以。。。。。n*?似乎可过????
数据貌似卡不了我复杂度,正解$O(nlogn)$,n极限在1e5,然后内层循环能循环250。。,因为他即使是构造的,但我仍是随机看人品更新的
然后多交两次就A了。
其实正确率还是蛮高的,在控制使n*k<=25000000的时候接近100%
n*k<=10000000的时候交3次WA1次。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<ctime> using namespace std; const int N=1000020; int w[N],a[N],f[N],cnt; long long rd() { long long s=0,w=1; char cc=getchar(); while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();} while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar(); return s*w; } int main() { //freopen("math5.in","r",stdin); srand(unsigned(time(0))); int n=rd(),k=rd(); for(int i=1;i<=n;i++) a[i]=rd(); for(int i=1;i<=n;i++) { if(!f[a[i]%k]) { f[a[i]%k]=1; w[++cnt]=a[i]%k; } } int ans=0; sort(w+1,w+cnt+1,greater<int>()); if(n==1) { int gcd=a[1]%k; for(int i=1;i<=k;i++) f[1ll*gcd*i%k]=1; for(int i=0;i<k;i++) ans=ans+f[i]; printf("%d\n",ans); for(int i=0;i<k;i++) if(f[i]) printf("%d ",i); puts(""); return 0; return 0; } if(k<=100) { for(int i=1;i<=cnt;i++) { for(int p=1;p<=k;p++) { int sum=0; for(int j=0;j<k;j++) { f[j]|=f[(j-w[i]+k)%k]; sum+=f[j]; } if(ans==sum) break; ans=max(ans,sum); } } printf("%d\n",ans); for(int i=0;i<k;i++) if(f[i])printf("%d ",i); puts(""); return 0; } else if(k<=1000) { for(int i=1;i<=cnt;i++) { for(int p=1;p<=k;p++) { int sum=0; for(int j=0;j<k;j++) { f[j]|=f[(j-w[i]+k)%k]; sum+=f[j]; } if(sum==ans) break; else ans=max(ans,sum); } } printf("%d\n",ans); for(int i=0;i<k;i++) if(f[i])printf("%d ",i); puts(""); return 0; } else { for(register int i=1;i<=cnt;++i) { for(register int p=1;p*cnt<=25000000;++p) { const int j=rand()%k; f[j]|=f[(j-w[i]+k)%k]; } } for(register int i=0;i<k;i++) ans+=f[i]; printf("%d\n",ans); for(register int i=0;i<k;i++) if(f[i])printf("%d ",i); puts(""); return 0; } } /* g++ -std=c++11 1.cpp -o 1 ./1 2 8 4 12 */