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 的代码(费马小定理):
#include <cstdio>
#include <algorithm>
#include <cstring> using namespace std ; const int maxn =; int sr , sb , sg , m , mod , f[ maxn ][ maxn ][ maxn ], a[ maxn *], n ;
bool used[ maxn *];
int v[ maxn *], cnt , ans =; void update(int&num ,int val ){
( num += val )%= mod ;
} int power(int val ,int times ){
int rec =;
for(; times ; times >>=){
if( times &)( rec *= val )%= mod ;
( val *= val )%= mod ;
}
return rec ;
} int main( ){
scanf("%d%d%d%d%d",&sr ,&sb ,&sg ,&m ,&mod );
n = sr + sb + sg ;
for(int w =; w ++< m +;){
if( w < m +)for(int i =; i ++< n ;)scanf("%d", a + i );
else for(int i =; i ++< n ;) a[ i ]= i ;
memset( used ,false,sizeof( used ));
cnt =;
for(int i =; i ++< n ;)if(! used[ i ]){
v[++ cnt ]=;
for(int j = i ;! used[ j ]; j = a[ j ]){
++ v[ cnt ], used[ j ]=true;
}
}
memset( f ,,sizeof( f ));
f[][][]=;
for(int h =; h ++< cnt ;){
for(int i = sr ; i >=;-- i ){
for(int j = sb ; j >=;-- j ){
for(int k = sg ; k >=;-- k ){
if( i >= v[ h ])update( f[ i ][ j ][ k ], f[ i - v[ h ]][ j ][ k ]);
if( j >= v[ h ])update( f[ i ][ j ][ k ], f[ i ][ j - v[ h ]][ k ]);
if( k >= v[ h ])update( f[ i ][ j ][ k ], f[ i ][ j ][ k - v[ h ]]);
}
}
}
}
update( ans , f[ sr ][ sb ][ sg ]);
}
( ans *=power( m +, mod -))%= mod ;
printf("%d\n", ans );
return ;
}
exgcd:
var s1,s2,s3,n,m,p,ans,i,j,x,y:longint;
a:array[..,..] of longint;
f:array[..,..,..] of longint;
function mo(x:longint):longint;
begin
mo:=x mod (p);
end;
procedure init;
begin
readln(s1,s2,s3,m,p);
n:=s1+s2+s3;
for i:= to m do
for j:= to n do
read(a[i,j]);
inc(m);
for i:= to n do a[m,i]:=i;
end;
function dp(x:longint):longint;
var i,j,k,tot,y,h,num:longint;
v:array[..] of boolean;
d:array[..] of longint;
begin
tot:=;
fillchar(v,sizeof(v),false);
for i:= to n do
if not(v[i]) then
begin
num:=;
v[i]:=true;
y:=i;
while a[x,y]<>i do
begin
y:=a[x,y];
v[y]:=true;
inc(num);
end;
inc(tot);
d[tot]:=num;
end;
fillchar(f,sizeof(f),);
f[,,]:=;
for h:= to tot do
for i:=s1 downto do
for j:=s2 downto do
for k:=s3 downto do
begin
if i>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i-d[h],j,k]);
if j>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j-d[h],k]);
if k>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j,k-d[h]]);
end;
exit(f[s1,s2,s3]);
end;
procedure exgcd(a,b:longint;var x,y:longint);
var t:longint;
begin
if a= then begin x:=;y:=;exit;end;
exgcd(b,a mod b,x,y);
t:=x;x:=y;y:=t-(a div b)*x;
end;
procedure main;
begin
ans:=;
for i:= to m do
ans:=mo(ans+dp(i));
exgcd(m,p,x,y);
while x< do inc(x,p);
writeln((ans*x) mod p);
end;
begin
init;
main;
end.
m*p:
var s1,s2,s3,n,m,p,ans,i,j,x,y:longint;
a:array[..,..] of longint;
f:array[..,..,..] of longint;
function mo(x:longint):longint;
begin
mo:=x mod (m*p);
end;
procedure init;
begin
readln(s1,s2,s3,m,p);
n:=s1+s2+s3;
for i:= to m do
for j:= to n do
read(a[i,j]);
inc(m);
for i:= to n do a[m,i]:=i;
end;
function dp(x:longint):longint;
var i,j,k,tot,y,h,num:longint;
v:array[..] of boolean;
d:array[..] of longint;
begin
tot:=;
fillchar(v,sizeof(v),false);
for i:= to n do
if not(v[i]) then
begin
num:=;
v[i]:=true;
y:=i;
while a[x,y]<>i do
begin
y:=a[x,y];
v[y]:=true;
inc(num);
end;
inc(tot);
d[tot]:=num;
end;
fillchar(f,sizeof(f),);
f[,,]:=;
for h:= to tot do
for i:=s1 downto do
for j:=s2 downto do
for k:=s3 downto do
begin
if i>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i-d[h],j,k]);
if j>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j-d[h],k]);
if k>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j,k-d[h]]);
end;
exit(f[s1,s2,s3]);
end;
procedure main;
begin
ans:=;
for i:= to m do
ans:=mo(ans+dp(i));
writeln((ans div m) mod p);
end;
begin
init;
main;
end.
HNOI2008Cards的更多相关文章
- BZOJ1004 HNOI2008Cards(Burnside引理+动态规划)
直接给了一个置换群(当然要自己手动加上不洗牌的情况).考虑求不动点数量即可.对于一个置换,求出所有循环的长度,然后设f[i][x][y]为给前i个循环着色后,用了x张红色卡片.y张绿色卡片的方案数,d ...
随机推荐
- mysql 拷贝表插入新的表
insert into table1 select * from table; insert into talble set name = value;
- 不得不知道的Python字符串编码相关的知识
开发经常会遇到各种字符串编码的问题,例如报错SyntaxError: Non-ASCII character 'ascii' codec can't encode characters in posi ...
- 十六、mysql 分区之 简单sql优化2
.索引的分类 B-Tree 基本支持 HASH 只有memory支持 R-Tree myisam支持 Full-text myisam支持(全文索引) .Memory引擎下只有“=”条件才会使用索引 ...
- iOS 通览(一) - 技巧、特性及规范
一.编译器特性 1.ARC. ARC是编译器特性.项目中使用了ARC,编译器会在项目编译的时候自动添加OC对象计数器release代码.并且使用了ARC,项目中将不允许出现release.retain ...
- js原生removeclass方法
//如果列表中有存在给定的值就删除 // function removeClass(ele,txt){ // var str = ele.className, // ary = str.split(/ ...
- Hibernate一对一单向外键关联
一.一对一单向外键关联: 一对一单向外键关联主要用到了以下两个注解: 1.OneToOne(cascade=CasecadeTYPE.ALL); cascade=CasecadeTYPE.ALL:表示 ...
- HTTP协议的几个重要概念
转自:http://ice-cream.iteye.com/blog/77549 1.连接(Connection):一个传输层的实际环流,它是建立在两个相互通讯的应用程序之间. 2.消息(Messag ...
- 优化Hoax or what的思考
在抽取MinHeap的时候,涉及到重载,覆盖,虚函数等,有几点之前没注意到的问题在这里总结下: 1. 覆盖(override)只要是函数同名就会被覆盖,子类指针若调用父类的同名不同参数的函数的话,会在 ...
- 算法总结之欧拉函数&中国剩余定理
算法总结之欧拉函数&中国剩余定理 1.欧拉函数 概念:在数论,对正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目. 通式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)( ...
- UML各种图画法总结
<UML 2.4.1 教程> http://www.sparxsystems.cn/resources/uml2_tutorial/ <UML总结(对九种图的认识和如何使用Ratio ...