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
  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 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){
 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::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;icc[i];
 48     ss[n].clear();
 49     dfs(0);
 50     ll temp=0,ans;
 51     while(m){
 52         for(set::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::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){
 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){
 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 }
巧妙的分类解决

 

你可能感兴趣的:(UVA 11754 Code Feat 中国剩余定理+枚举)