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 ...
随机推荐
- SQL*Loader使用详解(一)
1.SQL*Loader介绍 1)SQL*Loader是一个从外部文件指加载数据到Oracle数据库的工具.语法类似于DB2的Load语法,但SQL*Loader支持各种load格式.选择性load和 ...
- sharepoint warmup
/---------------- using System;using System.Collections.Generic; using System.Text;using System.Net; ...
- ITaCS Change Password web part
http://changepassword.codeplex.com/ A webpart is used to change your sharepoint AD password.
- sqlserver自定义函数【粘】
用户定义自定义函数像内置函数一样返回标量值,也可以将结果集用表格变量返回 用户自定义函数的类型: 标量函数:返回一个标量值 表格值函数{内联表格值函数.多表格值函数}:返回行集(即返回多个值) 1. ...
- SQL一列多行字符串分组合并
最近工作遇到如下数据:需要合并后只剩下两行的数据,普通的group by 是不能实现的.(如图) 利用如下SQL代码,即可实现需求(如图): 利用 stuff 函数实现分拆合并操作 select Te ...
- 基于Ogre的DeferredShading(延迟渲染)的实现以及应用
http://blog.sina.com.cn/s/blog_458f871201017i06.html 这篇文章写的不错,从比较宏观的角度说了下作者在OGRE中实现的延迟渲染
- HTML5 中的块级链接
英文叫做 “Block-level” links,我以为只有我厂那些鸟毛不知道,没想到不知道的还挺多, 需要普及一下. 最近看了 kejun 的 PPT 前端开发理论热点面对面:从怎么看,到怎么做?, ...
- 学习javascript总结下来的性能优化的小知识(一)
http://www.cnblogs.com/ctriphire/p/4115525.html http://www.cnblogs.com/xjchenhao/archive/2012/10/22/ ...
- Docker 监控实战
如今,越来越多的公司开始使用 Docker 了,现在来给大家看几组数据: 2 / 3 的公司在尝试了 Docker 后最终使用了它 也就是说 Docker 的转化率达到了 67%,而转化市场也控制在 ...
- Altium Designer13 如何导出Gerber文件
参考<http://blog.sina.com.cn/s/blog_9b9a51990100zyyv.html> 版本:AD13.3.4 目的:Gerber文件导出备忘 目录: Step1 ...