题目大意:求一个数N,给出C和S,表示有C个条件,每个条件有X 和 k,然后是该个条件的k个yi,即NmodX=yj,输出满足的最小的S个N,要求正整数。
解题思路:tot为所有的k的乘积,也就是可以作为一组完整限定条件的可能数.当个tot较小可以用中国剩余定理处理,但是如果tot太大的话,可以通过枚举N来判断,找到一组k/X最小的做为枚举基准,然后判断即可,t*X+Y[i](t=0,1,2...).
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include<cstdlib> 4 #include<cctype> 5 #include<cstring> 6 #include<vector> 7 #include<cassert> 8 #include<set> 9 #include<algorithm> 10 #define LL long long 11 using namespace std; 12 13 // 即使a, b在int范围内,x和y有可能超出int范围 14 void gcd(LL a, LL b, LL& d, LL& x, LL& y) 15 { 16 if(!b) 17 { 18 d = a; 19 x = 1; 20 y = 0; 21 } 22 else 23 { 24 gcd(b, a%b, d, y, x); 25 y -= x*(a/b); 26 } 27 } 28 29 // n个方程:x=a[i](mod m[i]) (0<=i<n) 30 LL china(int n, int* a, int *m) 31 { 32 LL M = 1, d, y, x = 0; 33 for(int i = 0; i < n; i++) M *= m[i]; 34 for(int i = 0; i < n; i++) 35 { 36 LL w = M / m[i]; 37 gcd(m[i], w, d, d, y); 38 x = (x + y*w*a[i]) % M; 39 } 40 return (x+M)%M; 41 } 42 43 const int maxc = 9; 44 const int maxk = 100; 45 const int LIMIT = 10000; 46 int C; 47 int X[maxk],k[maxc]; 48 int Y[maxc][maxk]; 49 set<int>values[maxc]; 50 51 void solve_enum(int S,int bc) 52 { 53 for(int c=0; c<C; c++) 54 if(c!=bc) 55 { 56 values[c].clear(); 57 for(int i=0; i<k[c]; i++) 58 { 59 values[c].insert(Y[c][i]); 60 } 61 } 62 for(int t=0; S!=0; t++) 63 { 64 for(int i=0; i<k[bc]; i++) 65 { 66 LL n=X[bc]*t+Y[bc][i]; 67 if(n==0) 68 continue; 69 bool ok=true; 70 for(int c=0; c<C; c++) 71 { 72 if(c!=bc) 73 { 74 if(!values[c].count(n%X[c])) 75 { 76 ok=false; 77 break; 78 } 79 } 80 } 81 if(ok) 82 { 83 printf("%lld ",n); 84 if(--S==0) 85 break; 86 } 87 } 88 } 89 } 90 int a[maxc]; 91 vector<LL>sol; 92 void dfs(int dep) 93 { 94 if(dep==C) 95 sol.push_back(china(C,a,X)); 96 for(int i=0;i<k[dep];i++) 97 { 98 a[dep]=Y[dep][i]; 99 dfs(dep+1); 100 } 101 } 102 103 void solve_china(int S) 104 { 105 sol.clear(); 106 dfs(0); 107 sort(sol.begin(),sol.end()); 108 LL M=1; 109 for(int i=0;i<C;i++) 110 M*=X[i]; 111 for(int i=0;S!=0;i++) 112 { 113 for(int j=0;j<sol.size();j++) 114 { 115 LL n=M*i+sol[j]; 116 if(n>0) 117 { 118 printf("%lld ",n); 119 if(--S==0) 120 break; 121 } 122 } 123 124 } 125 } 126 int main() 127 { 128 int S; 129 while(scanf("%d%d",&C,&S)==2&&C) 130 { 131 LL tot=1; 132 int bestc=0; 133 for(int c=0; c<C; c++) 134 { 135 scanf("%d%d",&X[c],&k[c]); 136 tot*=k[c]; 137 for(int i=0; i<k[c]; i++) 138 { 139 scanf("%d",&Y[c][i]); 140 } 141 sort(Y[c],Y[c]+k[c]); 142 if(k[c]*X[bestc]<k[bestc]*X[C]) 143 bestc=c; 144 } 145 if(tot>LIMIT) 146 solve_enum(S,bestc); 147 else 148 solve_china(S); 149 printf(" "); 150 } 151 return 0; 152 }