看了一下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的更多相关文章

  1. BZOJ1004 HNOI2008Cards(Burnside引理+动态规划)

    直接给了一个置换群(当然要自己手动加上不洗牌的情况).考虑求不动点数量即可.对于一个置换,求出所有循环的长度,然后设f[i][x][y]为给前i个循环着色后,用了x张红色卡片.y张绿色卡片的方案数,d ...

随机推荐

  1. VS2005打开VS2008 VS2010 VS2012

    我用vs2005较多,但网上找的代码经常是08 10 或者2012的,总结了以下技巧可以打开工程比较小巧的高版本代码. <1>用记事本打开解决方案文件“解决方案名.sln”,然后修改最上面 ...

  2. 开博第一篇:DHT 爬虫的学习记录

    经过一段时间的研究和学习,大致了解了DHT网络的一些信息,大部分还是参会别人的相关代码,一方面主要对DHT爬虫原理感兴趣,最主要的是为了学习python,大部分是别人的东西原理还是引用别人的吧 DHT ...

  3. JS 实现取整

    Js 常用数值函数(Math,parseInt)取整   1.丢弃小数部分,保留整数部分parseInt(5/2) 2.向上取整,有小数就整数部分加1Math.ceil(5/2) 3,四舍五入.Mat ...

  4. Hibernate从入门到精通(九)一对多双向关联映射

    上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映射,即在一的 ...

  5. C#学习笔记---基础入门(一)

    C#中的变量: 一个变量就是存储区(内存)中的一个存储单元. 变量声明赋值:int money =1000;/int money;money=1000; 输出:console.writeLine(mo ...

  6. Begin Andriod -- 安装android开发环境

    很久以前学过Andriod,现在已经忘的快没有了,重新捡起来练练,顺带写写博客,感受下写博的乐趣. 第一步:安装java jdk.jre(jdk:开发环境,jre:运行环境). (一)java jdk ...

  7. springMVC+MyBatis+Spring 整合(2)

    mybatis 与Spring 的整合. 1.导入Spring 和Springmvc的包 pom <project xmlns="http://maven.apache.org/POM ...

  8. xfire for web-Service

    1.0 XFire XFire是codeHaus组织提供的一个开源框架,它构建了POJO和SOA之间的桥梁,主要特性就是支持将POJO通过非常简单的方式发布成Web服务,这种处理方式不仅充分发挥了PO ...

  9. Linux下使用GDB调试程序

    问题描述:          Linux下使用GDB调试程序 问题解决:          (1)生成调试文件 注:         使用命令   gdb IOStream.c   -o IOStre ...

  10. ASP + ACCESS保存图片文件之实现

    con.execute "CREATE tblImg (lngId COUNTER PRIMARY KEY, binImg IMAGE)" set ads=createobject ...