求:用C种颜色染N阶完全图的不同染色方案(mod P),P为素数(两个染色方案是相同的当且仅当顶点编号重排后各边的颜色相同),其中1<=N<=53,1<=C<=1000;很明显这个群有N!个置换(顶点的排列),一个置换可表示为 (a1,a2,……,am)(b1,b2,……,bn)(c1,c2,……,ck) ……循环节的形式,其中m+n+k=N。以下证明: 1: 在一个置换下,关联的顶点都在某个L长的循环节的边,可分成一共floor(L/2)个等价类。2:在一个置换下,关联的顶点分别在两个长度为L1,L2的循环节内的边,可分成一共gcd(L1,L2)个等价类。证明1: 在下面的证明中[x] 表示 (x mod L)由于边{a[i],a([i]+[k])},{a[j],a([j]+[k])} ([k]>=1 && k<=L-1)在同一个等价类 ,而且 {a[i],a([i]+[k])} 与 {a[i],a([i]+[L-k])}在同一个等价类,所以[k]={1,2,3,……,floor(L/2)} 和 [k]={L-1,L-2,……,ceil(L/2)}分别对应同一个等价类。所以1得证。证明2:若v1属于{a1,a2,……,am},v2属于{b1,b2,……,bn},则{v1,v2}的等价边为 {v1+[t],v2+[t]},其中,在t从 1开始增加的过程中,首次出现v1==v1+[t] && v2==v2+[t] 是在 t=lcm(m,n)的时候,所以每一条边共有lcm(m,n)条等价边,所以共有 m*n/lcm(m,n)个等价类 即为 gcd(m,n);如果一个置换可以表示为 长度分别为 L1,L2,……,Lk(非降序排列)的k个循环节,那么在这个置换下边共有 n=Sum(floor(Li/2) ) + Sum(gcd(Li,Lj))个置换群;而 k1*L1+k2*L2+k3*L3+……km*Lm=N(其中 Li != Lj for i != j) 的置换共有 (N! *( (L1-1)! )^k1 *( (L2-1)!)^k2 *……* ((Lm-1)!)^km ) / ( ( (L1!)^k1 * (L2!)^k2 * (L3!)^k3*……(Lm!)^km )* (k1! * k2! * k3!*……*km!) )即为 tot = N!/( (L1^k1)*(L2^k2)*(L3^k3)*……(Lm^km) * (k1! * k2! * k3! * …… *km!));所以可以表示成这个形式(k1*L1+k2*L2+k3*L3+……+km*Lm)的固定构型个数为 ans= n* pow (C,tot) 个。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int max_n=60; 7 typedef long long LL; 8 9 int N,C,P; 10 11 LL facv[max_n],inv[max_n]; 12 13 LL mypow(LL a,LL b){ 14 LL res=1,radix=a%P; 15 while(b){ 16 if(b&1){ 17 res*=radix; res%=P; 18 } 19 radix*=radix; radix%=P; 20 b>>=1; 21 } 22 return res; 23 } 24 25 LL cal_inv(int i){ 26 return mypow(i,P-2); 27 } 28 29 int gcd(int i,int j){ 30 if(j==0) return i; 31 return gcd(j,i%j); 32 } 33 void ini(){ 34 facv[1]=1; 35 inv[1]=1; 36 for(int i=2;i<=N;i++){ 37 inv[i]=cal_inv(i); 38 facv[i]=facv[i-1]*inv[i]; facv[i]%=P; 39 } 40 } 41 42 int factor[max_n][2]; LL ans; 43 44 void search(int sum,int top){ 45 if(sum==N){ 46 LL n=1; 47 for(int i=1;i<=top;i++){ 48 int len=factor[i][0],cnt=factor[i][1]; 49 n*=mypow(inv[len],cnt); n%=P; 50 n*=facv[cnt]; n%=P; 51 } 52 LL tot=0; 53 for(int i=1;i<=top;i++){ 54 55 int len=factor[i][0],cnt=factor[i][1]; 56 tot+=cnt*(len/2); //the same circle 57 tot+=cnt*(cnt-1)/2*len; //two different circle 58 59 for(int j=i+1;j<=top;j++){ 60 int len_j=factor[j][0], cnt_j=factor[j][1]; 61 tot+=(cnt*cnt_j*gcd(len_j,len)); 62 } 63 } 64 ans+=(n*mypow(C,tot))%P; ans%=P; 65 return; 66 } 67 if(sum+factor[top][0]>=N){ 68 return; 69 } 70 for(int i=factor[top][0]+1;i<=N-sum;i++){ 71 for(int j=1;sum+i*j<=N;j++){ 72 factor[top+1][0]=i; factor[top+1][1]=j; 73 search(sum+i*j,top+1); 74 } 75 } 76 } 77 int main() 78 { 79 while(scanf("%d%d%d",&N,&C,&P)!=EOF){ 80 ini(); 81 factor[0][0]=0; 82 ans=0; 83 search(0,0); 84 printf("%lld\n",ans); 85 } 86 return 0; 87 } 88
|
|
CALENDER
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
27 | 28 | 29 | 30 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
常用链接
留言簿
随笔分类
随笔档案
搜索
最新评论
阅读排行榜
评论排行榜
Powered By: 博客园 模板提供:沪江博客
|