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 }
