bzoj2142

来源:互联网 发布:远景论坛 知乎 编辑:程序博客网 时间:2024/06/03 18:52

参考链接:

http://blog.csdn.net/popoqqq/article/details/39891263

http://blog.csdn.net/yerongsc/article/details/8768957

需要转化一下:

ans=C(n,w1)*C(n-w1,w2)*C(n-w1-w2,w3)*...*C(n-w1-w2-...-w_(m-1),wm) mod P

     =n!/w1!/w2!/.../wm! mod P


假设P=p1^a1*p2^a2+……+pn^an

这个题转化成中国剩余定理时应该模上p1^a1,p2^a2……,pn^an (1),而不是模上p1,p2,……pn(2)

假设按照第2种方法算出来符合条件的x,x加上或减去p1*p2*……*pn,仍符合条件,但是这样就有可能在0到P-1之间存在一个以上符合条件的,那么就不能确定是哪一个,因为一个确定的数模上P也是一个确定的数,在0到P-1之间只有一个值。

(跟这帮二百五一起执行任务,就像骑士骑着叫驴冲向战场,即便你高举马刀吼声如雷已经有为国捐躯之志,你也没法确定自己能杀入敌阵。因为你胯下的驴随时会撒起欢来甩开四蹄带你奔向天边。  ——江南 《龙族》大笑

2015.10.29:

话说什么味的棒棒糖好吃呢?本来吃腻了橘子味的,可是最近发现还是橘子的好吃,甜!!!!!羡慕

已ac的代码:

#include<stdio.h>#include<string.h>#include<iostream>using namespace std;#define M 10#define N 100010int pergift[M];int pi[N];int perpi[N];int picou;int b[N];long long int km(long long int x,int y,int mod){    long long int ans=1;    while(y){        if(y%2){            ans=ans*x%mod;        }        x=x*x%mod;        y=y/2;    }    return ans;}pair<int,int> ffa(int x,int mod,int permod){    //printf("wo shi da hao ren");    //printf("%d %d %dha\n",x,mod,permod);    if(x==0){        return make_pair(0,1);    }    else{        long long int ans=1;        pair<int,int> temp;        for(int i=1;i<=mod-1;i++){//少写了个=号            if(i%permod!=0){                ans=ans*i%mod;            }        }        ans=km(ans,x/mod,mod);//km返回long long int型        for(int i=1;i<=x%mod;i++){            if(i%permod!=0){                ans=ans*i%mod;            }        }        temp=ffa(x/permod,mod,permod);        ans=ans*temp.second%mod;        temp.second=ans;        temp.first+=x/permod;        //printf("%d %d %d %d %dha\n",x,mod,permod,temp.first,temp.second);        return temp;    }}void exgcd(long long int *a,long long int *b,int x,int y){    if(y==0){        *a=1;        *b=1;        return;    }    else{        long long int a1,b1;        exgcd(&a1,&b1,y,x%y);        *a=b1;        *b=a1-x/y*b1;        return;    }}int inv(int x,int y){    long long int a,b;    exgcd(&a,&b,x,y);    a=(a%y+y)%y;    return (int)a;}int calculate(int n,int m,int mod,int permod){    pair<int,int> pn,pm,tempp;    pn=ffa(n,mod,permod);    //printf("%d %d %d %d %d\n",n,mod,permod,pn.first,pn.second);    pm.first=0;    pm.second=1;    for(int i=0;i<m;i++){        tempp=ffa(pergift[i],mod,permod);        pm.first+=tempp.first;        pm.second=(long long int)pm.second*tempp.second%mod;    }    return km(permod,pn.first-pm.first,mod)*pn.second%mod*inv(pm.second,mod)%mod;//pn和pm写反了,这里这个式子计算完后,本来是long long int型的,但是因为返回int型的,看来自动转化成了int,不强制转化也是可以的。}long long int bigpro(long long int a,long long int b,long long int mod){    long long int ans=0;    while(b){        if(b%2){            ans=(ans+a)%mod;        }        a=(a+a)%mod;        b=b/2;    }    return ans;}long long int fwaycou(int n,int m,long long int p){    long long int tempp=p;    long long int ans=0;    picou=0;    for(int i=2;i*i<=tempp;i++){        if(tempp%i==0){            pi[picou]=1;            while(tempp%i==0){                pi[picou]*=i;                tempp/=i;            }            perpi[picou++]=i;        }    }    if(tempp!=1){//恭喜,又一次成功的忘记了这个判断!        pi[picou]=tempp;        perpi[picou++]=tempp;    }    for(int i=0;i<picou;i++){        b[i]=calculate(n,m,pi[i],perpi[i]);        //printf("%d\n",b[i]);    }    ans=0;    for(int i=0;i<picou;i++){        //printf("%lld %lld %d ha1\n",bigpro(p/pi[i],b[i],p),bigpro(bigpro(p/pi[i],b[i],p),inv(p/pi[i],pi[i]),p),inv(p/pi[i],pi[i]));        ans=(ans+bigpro(bigpro(p/pi[i],b[i],p),inv(p/pi[i],pi[i]),p))%p;//ans加上一个数后,忘了%p,所以wr了。    }    return ans;}int main(){    long long int p;    int n,m;    while(scanf("%lld",&p)!=EOF){        scanf("%d%d",&n,&m);        int sum=0;        for(int i=0;i<m;i++){            scanf("%d",&pergift[i]);            sum+=pergift[i];        }        if(sum>n){            printf("Impossible\n");        }        else{            pergift[m++]=n-sum;            printf("%lld\n",fwaycou(n,m,p));        }    }    return 0;}

又一遍ac代码:

#include<stdio.h>#include<string.h>#include<iostream>using namespace std;#define N 10#define M 100010int pergift[M];int pi[N];int picou;int perpi[N];int b[N];long long int km(long long int x,long long int y,long long int mod){//注意x要是long long int型的,因为在x*x时int可能超范围。    long long int ans=1;    while(y){        if(y%2){            ans=ans*x%mod;        }        y=y/2;        x=x*x%mod;    }    return ans;}pair<int,int> ffa(int n,int mod,int permod){    pair<int,int> ans;    //printf("%d %d %d\n",n,mod,permod);    if(n==0){        ans.first=0;        ans.second=1;    }    else{        long long int temp=1;        for(int i=1;i<mod;i++){            if(i%permod!=0){                temp=temp*i%mod;            }        }        temp=km(temp,n/mod,mod);        for(int i=1;i<=n%mod;i++){            if(i%permod!=0){                temp=temp*i%mod;            }        }        ans=ffa(n/permod,mod,permod);        ans.first+=n/permod;        ans.second=(int)(temp*ans.second%mod);    }    //printf("wo shi da hao ren");    return ans;}long long int bigpro(long long int x,long long int y,long long int mod){    long long int ans=0;    while(y){        if(y%2){            ans=(ans+x)%mod;        }        y=y/2;        x=(x+x)%mod;    }    return ans;}void exgcd(long long int *a,long long int *b,int x,int y){    if(y==0){        *a=1;        *b=1;    }    else{        long long int a1,b1;        exgcd(&a1,&b1,y,x%y);        *a=b1;        *b=a1-x/y*b1;    }    return;}int inv(int x,int y){    long long int a,b;    exgcd(&a,&b,x,y);    return (int)((a%y+y)%y);}int qmod(int n,int m,int mod,int permod){    pair<int,int> pn,pm,temp;    pn=ffa(n,mod,permod);    pm.first=0;    pm.second=1;    for(int i=0;i<m;i++){        temp=ffa(pergift[i],mod,permod);        pm.first+=temp.first;        pm.second=(int)((long long int)pm.second*temp.second%mod);    }    return (int)(km(permod,pn.first-pm.first,mod)*pn.second%mod*inv(pm.second,mod)%mod);//km要返回long long int型的}long long int fop(int n,int m,long long int p){    long long int tempp=p;    long long int ans=0;    picou=0;    for(int i=2;i*i<=tempp;i++){//当p是1时可以吗?        if(tempp%i==0){            pi[picou]=1;            while(tempp%i==0){                pi[picou]*=i;                tempp/=i;            }            perpi[picou++]=i;        }    }    if(tempp!=1){        pi[picou]=tempp;        perpi[picou++]=tempp;    }    for(int i=0;i<picou;i++){        b[i]=qmod(n,m,pi[i],perpi[i]);    }    for(int i=0;i<picou;i++){//这里是要应用中国剩余定理,合并同余方程,所以应该是遍历所有可能的余数,而不是m,m和这里完全没有任何关系。        //printf("%d\n",b[i]);        ans=(ans+bigpro(bigpro(p/pi[i],b[i],p),inv(p/pi[i],pi[i]),p))%p;//printf("wo shi da hao ren\n");    }    return ans;}int main(){    long long int p;    int n,m;    int sum;    while(scanf("%lld\n",&p)!=EOF){        scanf("%d%d",&n,&m);        sum=0;        for(int i=0;i<m;i++){            scanf("%d",&pergift[i]);            sum+=pergift[i];        }        if(n<sum){            printf("Impossible\n");        }        else{            pergift[m++]=n-sum;            printf("%lld\n",fop(n,m,p));//printf("wo shi da hao ren");        }    }    return 0;}


0 0
原创粉丝点击