POJ burnside&&polya整理练习
POJ 2409 Let it Bead
这题就是polya公式的直接套用,唯一麻烦的是置换群的种类数,由于可以翻转,所以除了要加上pow(c,gcd(s,i))这些平面旋转的置换群,还要加上翻转的。由于翻转的情况奇偶是不同的,所以需要分开讨论:偶数:pow(c,(s-2)/2+2)*(s/2)+pow(c,(s/2))*(s/2);(里面包含了两个对点和两个对边的旋转) 奇数:pow(c,(s-1)/2+1)*s;(一个点和对边的旋转)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int gcd(int a,int b)
{
if(b==0)
{
return a;
}
else
{
return gcd(b,a%b);
}
}
int pow(int x,int y)
{
int i,j=1;
for(i=0;i<y;++i)
{
j*=x;
}
return j;
}
int main()
{
int c,s,i,j,ans,sum;
while(1)
{
RD(c);
RD(s);
if(c==0&&s==0)
{
break;
}
sum=0;
for(i=1;i<=s;++i)
{
sum+=pow(c,gcd(i,s));//通用做法,而且数据量很小。
}
if(s%2==0)//注意题意,这题的图案是可以翻转的,但并不是所有题目都这样,注意观察
{
sum+=pow(c,(s-2)/2+2)*(s/2)+pow(c,(s/2))*(s/2);
}
else
{
sum+=pow(c,(s-1)/2+1)*s;
}
ans=sum/(2*s);
printf("%d\n",ans);
}
return 0;
}
POJ 1286 Necklace of Beads
典型的买一送一题,和上题一样,都是套用公式题目,这题和上题相比,还少了可以翻转的条件,而且颜色数量固定为3,所以就不过多赘述了。但要注意N=0时要特判一下,输出0。而且数据范围比之前那题大,要使用long long。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int gcd(int a,int b)
{
if(b==0)
{
return a;
}
else
{
return gcd(b,a%b);
}
}
long long pow(int x,int y)//注意数据范围,3的18次方就超了
{
int i;
long long j=1;
for(i=0; i<y; ++i)
{
j*=x;
}
return j;
}
int main()
{
int s,i;
long long ans,sum;
while(1)
{
scanf("%d",&s);
if(s==-1)
{
break;
}
if(s==0)
{
printf("0\n");
}
else
{
sum=0;
for(i=1; i<=s; ++i)
{
sum+=pow(3,gcd(i,s));
}
if(s%2==0)
{
sum+=pow(3,(s-2)/2+2)*(s/2)+pow(3,(s/2))*(s/2);
}
else
{
sum+=pow(3,(s-1)/2+1)*s;
}
ans=sum/(2*s);
printf("%lld\n",ans);
}
}
return 0;
}
POJ 2154 Color
这题就不是简单的套用公式就可以过了,由于数据量很大,所以我们就需要使用筛素数结合欧拉函数求解的方式优化复杂度。而且数据范围的原因,很多人为了图省事,确保不会吵范围就用long long定义了事,却发现TLE,所以在写这题是必须还是要使用int定义,而且需要在很多地方取模。注意:快速幂部分取模一定要频繁,每个数在进行运算之前都需要取模。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int N;
int p(int x,int y)//取模一定要反复,我就是因为这个WA的
{
int res=1;
while(y>0)
{
if(y%2==1)
{
res=(res%N)*(x%N)%N;
}
x=(x%N)*(x%N)%N;
y/=2;
}
return res%N;
}
int e(int n)
{
int ans=1,i;
for(i=2; i*i<=n; i++)
{
if(n%i==0)
{
ans*=i-1;
n/=i;
while(n%i==0)
{
ans*=i;
n/=i;
}
}
}
if(n>1)
{
ans*=n-1;
}
return ans;
}
int main()
{
int i,t,s;
__int64 sum;
RD(t);
while(t--)
{
scanf("%d%d",&s,&N);
sum=0;
for(i=1; i*i<=s; ++i)
{
if(s%i==0)
{
sum=(sum+e(s/i)%N*p(s,i-1))%N;//这是求polya计数的通用优化方式
if(i*i!=s)
{
sum=(sum+e(i)%N*p(s,s/i-1))%N;//也要注意取模方式
}
}
}
printf("%I64d\n",sum%N);
}
return 0;
}
POJ 2888 Magic Bracelet
超好的组合题,这题是burnside的范围,因为burnside求有限制条件的组合数是很有效果的。这题用到了很多知识burnside+矩阵乘+矩阵快速幂+快速幂取模+欧拉函数+筛素数法+离散数学的知识。运用离散数学的知识将珠子的组合关系建图,转化为矩阵就是1为a和b可联通,0为a和b不可相联。而此矩阵的k次方就代表了经过k条路到达的方案数。
然后再结合欧拉函数优化就可以得到答案了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 9973
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int s,m,k,tx[11][11],ty[11][11],tz[11][11];
int p(int x,int y)//快速幂取模
{
int res=1;
x=x%N;
while(y>0)
{
if(y%2==1)
{
res=(res*x)%N;
}
x=(x*x)%N;
y/=2;
}
return res%N;
}
int e(int n)//欧拉函数优化
{
int ans=1,i;
for(i=2; i*i<=n; i++)
{
if(n%i==0)
{
ans*=i-1;
n/=i;
while(n%i==0)
{
ans*=i;
n/=i;
}
}
}
if(n>1)
{
ans*=n-1;
}
return ans%N;//注意取模,不然会超
}
void mat(int a[11][11],int b[11][11])//矩阵乘
{
int d[11][11],i,j,l;
mem(d,0);
For(0,m,i)
{
For(0,m,j)
{
For(0,m,l)
{
d[i][j]=(d[i][j]+a[i][l]*b[l][j])%N;
}
}
}
For(0,m,i)
{
For(0,m,j)
{
a[i][j]=d[i][j];
}
}
}
int g(int x)
{
mem(ty,0);
int i,j,ans;
For(0,m,i)
{
For(0,m,j)
{
tz[i][j]=tx[i][j];
}
}
For(0,m,i)
{
ty[i][i]=1;
}
while(x>0)//矩阵快速幂
{
if(x%2==1)
{
mat(ty,tz);
}
mat(tz,tz);
x/=2;
}
ans=0;
For(0,m,i)
{
ans=(ans+ty[i][i])%N;
}
return ans;
}
int main()
{
int i,j,t,a,b;
int sum;
RD(t);
while(t--)
{
RD(s);
RD(m);
RD(k);
For(0,m,i)
{
For(0,m,j)
{
tx[i][j]=1;
}
}
For(0,k,i)
{
RD(a);
RD(b);
a--;
b--;
tx[a][b]=tx[b][a]=0;//建图
}
sum=0;
for(i=1; i*i<=s; ++i)
{
if(s%i==0)//其他过程与上题类似
{
sum=(sum+(e(s/i)*g(i))%N)%N;
if(i*i!=s)
{
sum=(sum+(e(i)%N*g(s/i))%N)%N;
}
}
}
printf("%d\n",(sum*(p(s,N-2)%N))%N);
}
return 0;
}
burnside&&polya还有很多神奇的应用,希望可以与大家多多交流经验~
POJ burnside&&polya整理练习的更多相关文章
- burnside+polya 整理
先定义几个含义和符号:起始状态/方法/位置/元素/:以染色为例,起始状态是所有的染色方案,方法是以起始状态所有染色方案为基准转变为新的染色情景的操作(如旋转),位置则必须是没有任何染色效果的抽象空间, ...
- Burnside&Polya总结
这里就算是一个小总结吧- 附参考的网址: http://blog.sina.com.cn/s/blog_6a46cc3f0100s2qf.html http://www.cnblogs.com/han ...
- Burnside&Polya总结
这里就算是一个小总结吧- 附参考的网址: http://blog.sina.com.cn/s/blog_6a46cc3f0100s2qf.html http://www.cnblogs.com/han ...
- Burnside&Polya
以前只是直接用了这两个式子..今天才仔细看了证明..[网上的真是难懂啊 我看的几个博客地址(各有优缺): 其实如果能懂的话 只看博客B就可以了 首先是一些置换群方面的定义和性质 博客A:http:/ ...
- bzoj1004 [HNOI2008]Cards【Burnside/Polya】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1004 一道好题,但并不是好在融合了三个“考点”(计数,背包dp,逆元),其实背包dp以及求逆 ...
- poj 1286 polya定理
Necklace of Beads Description Beads of red, blue or green colors are connected together into a circu ...
- poj 2409(polya定理模板)
题意:给你n种颜色和m个小球,问你有多少种不同的方案! 分析:作为模板.. 代码实现: #include <iostream> #include <cstdio> #inclu ...
- 等价类计数:Burnside引理 & Polya定理
提示: 本文并非严谨的数学分析,有很多地方是自己瞎口胡的,仅供参考.有错误请不吝指出 :p 1. 群 1.1 群的概念 群 \((S,\circ)\) 是一个元素集合 \(S\) 和一种二元运算 $ ...
- Polya计数
Let it Bead Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5365 Accepted: 3585 Descr ...
随机推荐
- hdu 5108
//题意是给一个数N,然后让你求M,使得N/M为素数,并且M的值最小 //思路呢,大概有两种,一个是遍历素数求解的,不过数据太大不现实 //另外一种就是质因数求解,for循环是遍历质因数,然后whil ...
- window.location.href 和self.location的区别
你从字面上就可以理解到 window 指的是当前窗口 而 self 指的是自己 在HTML 中 由于页面可以镶嵌页面 所以这2个就有了 区别 比如说 我有个页面A.HTML 里面嵌套了一个B.HTML ...
- rest简单实例
http://www.cnblogs.com/fredric/archive/2012/03/03/2378680.html http://www.thinksaas.cn/topics/0/153/ ...
- JavaScript 函数之 ------------------ 闭包
谈到闭包,人们常常会把匿名函数和闭包混淆在一起.闭包是指由权访问另一个函数作用域中的变量的函数.创建闭包的常见方式,就是在一个函数内部创建另一个函数,仍以前面的 createComparisonFun ...
- Javascript 中神奇的 this
Javascript 当中的 this 与其他语言是完全不同的机制,很有可能会让一些编写其他语言的工程师迷惑. 1. 误以为 this 指向函数自身 根据 this 的英语语法,很容易将函数中出现的 ...
- JS操作css的float属性的特殊写法
使用js操作css属性的写法是有一定的规律的: 1.对于没有中划线的css属性一般直接使用style.属性名即可. 如:obj.style.margin,obj.style.width,obj.sty ...
- HTML资源(推荐)
W3C在线验证工具:http://validator.w3.org/ (X)HTML嵌套规则:http://www.cnblogs.com/PeunZhang/archive/2012/03/11/2 ...
- android popupwindow低版本报空指针
在项目中使用Popupwindow pop=new Popupwindow();在2.3版本报 异常信息: Exception: null 堆栈信息: android.widget.PopupWind ...
- z-index的最大值、最小值
浏览器 最大值 超过最大值后变成 最小值 小于最小值后变成 备注 IE6 2147483647 2147483647 -2147483648 -2147483648 IE7 2147483647 ...
- AD14中如何定义PCB尺寸大小(不同于AD9和10)
以前用的着软件基本都是停留在9和10,14用的少,虽然14增加了很多功能,但是也带来了不变,虽然可以打开各种其他格式的文件,但是有些地方的改动不容忽略,在一个完整的板子下来需要用到的每个地方的点也会有 ...