UVA 11754 Code Feat 中国剩余定理+枚举
Code FeatUVA - 11754
题意:给出c个彼此互质的xi,对于每个xi,给出ki个yj,问前s个ans满足ans%xi的结果在yj中有出现过。
一看便是个中国剩余定理,但是同余方程组就有ki的乘积种组合,而ki的乘积最大是1e18,直接中国剩余定理肯定不是的,只能对ki的乘积稍微小的时候才能使用。
而当ki的乘积很大时,便说明对于每个xi它的yj都很多,那么我们挑选其中一组xi,设ans=temp*xi+yj,temp不需要枚举到很大便能满足其他的%xi=yj,
至于那组xi的选择,因为我们是要枚举得更快,所有便是yj尽可能的多,xi尽可能的大,也就是ki/xi最小。
最后注意输出格式上,空行的输出。
1 #include<cstdio> 2 #include<set> 3 using namespace std; 4 typedef long long ll; 5 const int N=15; 6 int n,m; 7 ll bb[N],cc[N],cp; 8 set<ll> ss[N]; 9 ll exgcd(ll a,ll b, ll &x,ll &y){ 10 if(!b){ 11 x=1; 12 y=0; 13 return a; 14 } 15 ll g=exgcd(b,a%b,y,x); 16 y-=a/b*x; 17 return g; 18 } 19 ll inv(ll a,ll c){ 20 ll g,x,y; 21 g=exgcd(a,c,x,y); 22 return g==1 ? (x%c+c)%c : -1; 23 } 24 ll crt(){ 25 ll ans=0,temp; 26 for(int i=0;i<n;i++){ 27 temp=cp/cc[i]; 28 ans+=bb[i]*temp*inv(temp,cc[i]); 29 if(ans>=cp) ans%=cp; 30 } 31 ans=(ans+cp)%cp; 32 if(!ans) ans+=cp; 33 return ans; 34 } 35 void dfs(int x){ 36 if(x==n){ 37 ss[n].insert(crt()); 38 return ; 39 } 40 for(set<ll>::iterator it=ss[x].begin();it!=ss[x].end();it++){ 41 bb[x]=*it; 42 dfs(x+1); 43 } 44 } 45 void solve1(){ 46 cp=1; 47 for(int i=0;i<n;i++) cp*=cc[i]; 48 ss[n].clear(); 49 dfs(0); 50 ll temp=0,ans; 51 while(m){ 52 for(set<ll>::iterator it=ss[n].begin();it!=ss[n].end();it++){ 53 ans=(*it)+temp*cp; 54 printf("%lld\n",ans); 55 m--; 56 if(!m) break; 57 } 58 temp++; 59 } 60 } 61 void solve2(int p){ 62 ll temp=0,ans; 63 while(m){ 64 for(set<ll>::iterator it=ss[p].begin();it!=ss[p].end();it++){ 65 ans=temp*cc[p]+(*it); 66 if(!ans) continue; 67 bool flag=true; 68 for(int i=0;i<n;i++){ 69 if(i==p) continue; 70 if(ss[i].find(ans%cc[i])==ss[i].end()){ 71 flag=false; 72 break; 73 } 74 } 75 if(flag){ 76 printf("%lld\n",ans); 77 m--; 78 } 79 if(!m) break; 80 } 81 temp++; 82 } 83 } 84 int main(){ 85 int k,p; 86 ll ji,x; 87 int t=0; 88 while(~scanf("%d%d",&n,&m)){ 89 if(t) printf("\n"); 90 t=1; 91 p=-1;ji=1; 92 for(int i=0;i<n;i++){ 93 ss[i].clear(); 94 scanf("%lld",&cc[i]); 95 scanf("%d",&k); 96 ji*=k; 97 if(p==-1||k*cc[p]<(int)ss[p].size()*cc[i]) p=i; 98 while(k--){ 99 scanf("%lld",&x); 100 ss[i].insert(x); 101 } 102 } 103 if(ji<=10000) solve1(); 104 else solve2(p); 105 } 106 return 0; 107 }
我太难了~给个三连吧,亲~~~