首页 > 代码库 > HNOI2008Cards
HNOI2008Cards
暗了一下polya和burnside定理,感觉还行(就是不会证……)
这题用的是burnside
ans=在每个置换群下不动的方案数之和除以置换数
这题有个难点在取模
关于对p(p为素数)取模(涉及到了除法),我总结了两种方法:
已知x mop p=y,要求x/z mod p=?
大体思路是利用乘法逆,将/z转换成*z的逆元即可
一、利用费马小定理
z^p-1 mod p=1
所以z的逆元=power_mod(z,p-2,p)
二、利用拓展欧几里德算法,即exgcd(z,p,x,y)
while x<0 do inc(x,p)
事实上,这也是乘法逆的思想
exgcd(z,p,x,y) 这实际上是在解同余方程zx mod p=1
x不就是z的逆元吗
但是当p不是素数时,应该怎么办呢?
在做noi2002robot的时候,我运用了一种特殊的方法,最后需要求x>>1 mod p=?
我在过程中始终对p取模,到最后感觉做不下去了
后来我灵机一动,想到了多取一位 在过程中mod 10p
这样 最后输出的时候再mod p 答案就正确了
不知道这样的方法能否应用在更广泛的地方……
ps:刚才试了一下此题
在过程中一直对m*p取模,最后ans div m 再对p取模,竟然AC了
原理在哪里?
代码:
神牛Green Clouds 的代码(费马小定理):
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std ; 6 7 const int maxn =21; 8 9 int sr , sb , sg , m , mod , f[ maxn ][ maxn ][ maxn ], a[ maxn *3], n ;10 bool used[ maxn *3];11 int v[ maxn *3], cnt , ans =0;12 13 void update(int&num ,int val ){14 ( num += val )%= mod ;15 }16 17 int power(int val ,int times ){18 int rec =1;19 for(; times ; times >>=1){20 if( times &1)( rec *= val )%= mod ;21 ( val *= val )%= mod ;22 }23 return rec ;24 }25 26 int main( ){27 scanf("%d%d%d%d%d",&sr ,&sb ,&sg ,&m ,&mod );28 n = sr + sb + sg ;29 for(int w =0; w ++< m +1;){30 if( w < m +1)for(int i =0; i ++< n ;)scanf("%d", a + i );31 else for(int i =0; i ++< n ;) a[ i ]= i ;32 memset( used ,false,sizeof( used ));33 cnt =0;34 for(int i =0; i ++< n ;)if(! used[ i ]){35 v[++ cnt ]=0;36 for(int j = i ;! used[ j ]; j = a[ j ]){37 ++ v[ cnt ], used[ j ]=true;38 }39 }40 memset( f ,0,sizeof( f ));41 f[0][0][0]=1;42 for(int h =0; h ++< cnt ;){43 for(int i = sr ; i >=0;-- i ){44 for(int j = sb ; j >=0;-- j ){45 for(int k = sg ; k >=0;-- k ){46 if( i >= v[ h ])update( f[ i ][ j ][ k ], f[ i - v[ h ]][ j ][ k ]);47 if( j >= v[ h ])update( f[ i ][ j ][ k ], f[ i ][ j - v[ h ]][ k ]);48 if( k >= v[ h ])update( f[ i ][ j ][ k ], f[ i ][ j ][ k - v[ h ]]);49 }50 }51 }52 }53 update( ans , f[ sr ][ sb ][ sg ]);54 }55 ( ans *=power( m +1, mod -2))%= mod ;56 printf("%d\n", ans );57 return 0;58 }
exgcd:
1 var s1,s2,s3,n,m,p,ans,i,j,x,y:longint; 2 a:array[0..70,0..70] of longint; 3 f:array[0..25,0..25,0..25] of longint; 4 function mo(x:longint):longint; 5 begin 6 mo:=x mod (p); 7 end; 8 procedure init; 9 begin10 readln(s1,s2,s3,m,p);11 n:=s1+s2+s3;12 for i:=1 to m do13 for j:=1 to n do14 read(a[i,j]);15 inc(m);16 for i:=1 to n do a[m,i]:=i;17 end;18 function dp(x:longint):longint;19 var i,j,k,tot,y,h,num:longint;20 v:array[0..70] of boolean;21 d:array[0..70] of longint;22 begin23 tot:=0;24 fillchar(v,sizeof(v),false);25 for i:=1 to n do26 if not(v[i]) then27 begin28 num:=1;29 v[i]:=true;30 y:=i;31 while a[x,y]<>i do32 begin33 y:=a[x,y];34 v[y]:=true;35 inc(num);36 end;37 inc(tot);38 d[tot]:=num;39 end;40 fillchar(f,sizeof(f),0);41 f[0,0,0]:=1;42 for h:=1 to tot do43 for i:=s1 downto 0 do44 for j:=s2 downto 0 do45 for k:=s3 downto 0 do46 begin47 if i>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i-d[h],j,k]);48 if j>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j-d[h],k]);49 if k>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j,k-d[h]]);50 end;51 exit(f[s1,s2,s3]);52 end;53 procedure exgcd(a,b:longint;var x,y:longint);54 var t:longint;55 begin56 if a=1 then begin x:=1;y:=0;exit;end;57 exgcd(b,a mod b,x,y);58 t:=x;x:=y;y:=t-(a div b)*x;59 end;60 procedure main;61 begin62 ans:=0;63 for i:=1 to m do64 ans:=mo(ans+dp(i));65 exgcd(m,p,x,y);66 while x<0 do inc(x,p);67 writeln((ans*x) mod p);68 end;69 begin70 init;71 main;72 end.
m*p:
1 var s1,s2,s3,n,m,p,ans,i,j,x,y:longint; 2 a:array[0..70,0..70] of longint; 3 f:array[0..25,0..25,0..25] of longint; 4 function mo(x:longint):longint; 5 begin 6 mo:=x mod (m*p); 7 end; 8 procedure init; 9 begin10 readln(s1,s2,s3,m,p);11 n:=s1+s2+s3;12 for i:=1 to m do13 for j:=1 to n do14 read(a[i,j]);15 inc(m);16 for i:=1 to n do a[m,i]:=i;17 end;18 function dp(x:longint):longint;19 var i,j,k,tot,y,h,num:longint;20 v:array[0..70] of boolean;21 d:array[0..70] of longint;22 begin23 tot:=0;24 fillchar(v,sizeof(v),false);25 for i:=1 to n do26 if not(v[i]) then27 begin28 num:=1;29 v[i]:=true;30 y:=i;31 while a[x,y]<>i do32 begin33 y:=a[x,y];34 v[y]:=true;35 inc(num);36 end;37 inc(tot);38 d[tot]:=num;39 end;40 fillchar(f,sizeof(f),0);41 f[0,0,0]:=1;42 for h:=1 to tot do43 for i:=s1 downto 0 do44 for j:=s2 downto 0 do45 for k:=s3 downto 0 do46 begin47 if i>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i-d[h],j,k]);48 if j>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j-d[h],k]);49 if k>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j,k-d[h]]);50 end;51 exit(f[s1,s2,s3]);52 end;53 procedure main;54 begin55 ans:=0;56 for i:=1 to m do57 ans:=mo(ans+dp(i));58 writeln((ans div m) mod p);59 end;60 begin61 init;62 main;63 end. 64
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。