首页 > 代码库 > POJ 2888

POJ 2888

思路挺清晰的。不过,我就是WA。不清楚为什么,很多数据都过了。

 

其实,一个置换后若有循环节个数为K,则N必定可以除以尽K。而K正好可以看成一个环。为什么呢?看前K个珠子,就是一个环,而后面的若干个K个珠子,不过就是不停的重复而已。这样,循环节的个数可以由最大公约数求得。那么,这个K个珠子构成的环符合题意的有多少种呢?很巧妙的一个方法是,用矩阵表示,若颜色相邻则I,J可以为1,否则为0。矩阵相乘有一个应用就是求的路径数啊。

 

最后,求逆元即可。可我的就是不过,求大神路过时指点。

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#define MOD 9973using namespace std;struct Matrix{	int m[12][12];}mat[50];int m;bool isprime[35000];int prime[35000],np;int dive[100],dn;Matrix operator * (Matrix a,Matrix b){	Matrix ret;	for(int i=1;i<=m;i++){		for(int j=1;j<=m;j++){			ret.m[i][j]=0;			for(int k=1;k<=m;k++){				ret.m[i][j]=(ret.m[i][j]+(a.m[i][k]*b.m[k][j])%MOD)%MOD;			}		}	}	return ret;}void getprime(){	memset(isprime,true,sizeof(isprime));	np=0;	for(int i=2;i<35000;i++){		if(isprime[i]){			prime[np++]=i;			for(int j=i*i;j<35000;j+=i){				isprime[j]=false;			}		}	}}void divn(int n){	dn=0;	int L =(int)sqrt(n*1.0);	for(int i=1;i<=L;i++){		if(n%i==0){			dive[dn++]=i;			if(i!=n/i)			dive[dn++]=n/i;		}	}}void getinit(){	for(int i=1;i<50;i++){		mat[i]=mat[i-1]*mat[i-1];	}}int phi(int p){	int n=p;	int res=p;	for(int i=0;i<np&&prime[i]*prime[i]<=n;i++){		if(p%prime[i]==0){			res=res-res/prime[i];			while(p%prime[i]==0)			p/=prime[i];		}	}	if(p>1)	res=res-res/p;	return res%MOD;}int quick(int b){	 Matrix ans;	 memset(ans.m,0,sizeof(ans.m));	 for(int i=1;i<=m;i++)	 ans.m[i][i]=1;	 int k=0;	 while(b){	 	if(b&1) ans=ans*mat[k];	 	b>>=1;	 	k++;	 }	 int res=0;	 for(int i=1;i<=m;i++)	 res=(res+ans.m[i][i])%MOD;	 return res;}void exgcd(int a,int b,int &x,int &y){	if(b==0){       x=1;       y=0;       return ;    }	exgcd(b,a%b,x,y);    int t=x;    x=y;    y=t-a/b*y;}void slove(int n,int m){	int x,y;	exgcd(n,MOD,x,y);	int ans=0;	for(int i=0;i<dn;i++){		ans=(ans+(phi(n/dive[i])%MOD)*quick(dive[i]))%MOD;	}	x=(x%MOD+MOD)%MOD;	ans=(ans*x)%MOD;	printf("%d\n",ans);}int main(){	int n,k,p,q,T;	getprime();	scanf("%d",&T);	while(T--){		scanf("%d%d%d",&n,&m,&k);		for(int i=1;i<=m;i++){			for(int j=1;j<=m;j++)			mat[0].m[i][j]=1;		}		for(int i=1;i<=k;i++){			scanf("%d%d",&p,&q);			mat[0].m[p][q]=mat[0].m[q][p]=0;		}		getinit();		divn(n);		slove(n,m);	}	return 0;}

  以下是别人的代码:http://blog.csdn.net/tmeteorj/article/details/8654330

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;typedef long long LL;const int mr=100000;const LL mod=9973;bool notp[mr];int pr[mr],fac[102],num[102];int pn,top,n,m;LL ans;struct MAT{    LL bas[13][13];    void init()    {        memset(bas,0,sizeof(bas));    }} mat[50];MAT mul(MAT a,MAT b){    MAT c;    c.init();    for(int i=1; i<=m; i++)        for(int k=1; k<=m; k++)        {            if(a.bas[i][k])            {                for(int j=1; j<=m; j++)                {                    c.bas[i][j]+=a.bas[i][k]*b.bas[k][j];                    if(c.bas[i][j]>=mod)                        c.bas[i][j]%=mod;                }            }        }    return c;}void getpri()//筛素数{    pn=0;    memset(notp,0,sizeof(notp));    for(int i=2; i<mr; i++)    {        if(!notp[i])        {            pr[pn++]=i;        }        for(int j=0; j<pn && i*pr[j]<mr; j++)        {            int k=i*pr[j];            notp[k]=1;            if(i%pr[j]==0)break;        }    }}void divn(){    int nn=n;    top=0;    int lim=(int)sqrt((double(nn)))+1;    for(int i=0; pr[i]<=lim; i++)    {        if(nn%pr[i]==0)        {            fac[top]=pr[i];            num[top]=0;            while(nn%pr[i]==0)                num[top]++,nn/=pr[i];            top++;        }    }    if(nn>1)        fac[top]=nn,num[top++]=1;}int phi(int x){    int i, res=x;    for (i=0;pr[i]<(int)sqrt((double)x)+1;i++)    if(x%pr[i]==0)    {        res=res/pr[i]*(pr[i]-1);        while(x%pr[i]==0)x/=pr[i];    }    if(x>1)res=res/x*(x-1);    return res;}void solve(int r){    int res=phi(n/r);    MAT mt;    mt.init();    for(int i=1;i<=m;i++)        mt.bas[i][i]=1;    for(int i=1,tp=r;tp;i++,tp>>=1)    if(tp&1)mt=mul(mt,mat[i]);    for(int i=1;i<=m;i++)    {        ans+=mt.bas[i][i]*res;        if(ans>=mod)ans%=mod;    }}void dfs(int id,int sum){    if(id==top)    {        solve(sum);        return;    }    else    {        dfs(id+1,sum);        for(int ct=0; ct<num[id]; ct++)            dfs(id+1,sum=sum*fac[id]);    }}void init(){    for(int i=2; i<50; i++)        mat[i]=mul(mat[i-1],mat[i-1]);}int Egcd (int a,int b, int &x, int &y){    if (b==0)    {        x=1,y=0;        return a;    }    LL d, tp;    d = Egcd (b, a%b, x, y);    tp = x;    x = y;    y = tp - a/b*y;    return d;}int getni(){    int x,y;    Egcd(n,mod,x,y);    return (x%mod+mod)%mod;}int main(){    getpri();    int T;    for(scanf("%d",&T); T; T--)    {        int k;        scanf("%d%d%d",&n,&m,&k);        ans=0;        for(int i=1; i<=m; i++)            for(int j=1; j<=m; j++)                mat[1].bas[i][j]=1;        for(int a,b,i=0; i<k; i++)        {            scanf("%d%d",&a,&b);            mat[1].bas[a][b]=mat[1].bas[b][a]=0;        }        init();        divn();        dfs(0,1);        printf("%d\n",ans*getni()%mod);    }    return 0;}

  

POJ 2888