[HDU2481]Toy(置换+矩阵乘法)
来源:互联网 发布:淘宝商品管理哪个好 编辑:程序博客网 时间:2024/05/27 00:32
=== ===
这里放传送门
=== ===
题解
一眼看到这个题的时候想到了BZOJ1002轮状病毒。。。实际上做这个题的时候也用到了那个题的结论。
结论:设
f(n) 为不同的(不考虑旋转同构)的n轮状病毒的个数,则f(n)=3∗f(n−1)−f(n−2)+2
这玩意儿当时是用基尔霍夫矩阵推出来的。。
但是这个题的话要考虑旋转同构诶,如何和那个题的结论联系起来呢?
Burnside引理:设有置换群
G={a1,a2...ag} ,c(ai) 为置换ai 作用下不动点的个数,那么这个置换群作用下等价类的个数为1G∑i=1gc(ai)
那么关键就是如何求出在每种置换作用下不动点的个数,也就是经过这个置换作用以后不变的方案数目。设旋转
可以发现如果这个图被分成了
那么如果要构造在置换
这说明这个连边方案只和循环节的个数有关,属于同一个循环节的点可以看成一个整体,而如果把循环节看成整体的话就相当于可以随便连边不用考虑什么同构限制了。那这就跟轮状病毒那个题是一样了。
设n轮状病毒的方案数为
用数学方法化一下式子就可以化成
注意的事情是这里的模数不一定和n互质,在做除法的时候没法求逆元,那只能先把
代码
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,prm[1000010];long long ans,m,f[5],Mod,phi[1000010];bool ext[1000010];inline long long mul(long long a,long long t){ long long ans=0; if (a<0) a+=Mod; if (t<0) t+=Mod; while (t!=0){ if (t&1) ans=ans+a; if (ans>=Mod) ans-=Mod; a=a+a;t>>=1; if (a>=Mod) a-=Mod; } return ans;}struct hxy{ long long s[5][5]; hxy(){memset(s,0,sizeof(s));} void clear(){ memset(s,0,sizeof(s)); for (int i=1;i<=3;i++) s[i][i]=1; } void get(){ memset(s,0,sizeof(s)); s[1][1]=1;s[3][2]=1;s[1][3]=2; s[2][3]=-1;s[3][3]=3; } hxy operator * (const hxy &a){ hxy c; long long *w; for (int i=1;i<=3;i++) for (int j=1;j<=3;j++){ w=&(c.s[i][j]); (*w)=((*w)+mul(s[i][1],a.s[1][j]))%Mod; (*w)=((*w)+mul(s[i][2],a.s[2][j]))%Mod; (*w)=((*w)+mul(s[i][3],a.s[3][j]))%Mod; } return c; }}w;hxy powww(hxy a,int t){ hxy ans; ans.clear(); while (t!=0){ if (t&1) ans=ans*a; a=a*a;t>>=1; } return ans;}void get_prime(int N){ phi[1]=1; for (int i=2;i<=N;i++){ if (ext[i]==false){ prm[++prm[0]]=i; phi[i]=i-1; } for (int j=1;j<=prm[0];j++){ if ((long long)i*prm[j]>N) break; ext[i*prm[j]]=true; if (i%prm[j]==0){ phi[i*prm[j]]=phi[i]*prm[j];break; }else phi[i*prm[j]]=phi[i]*phi[prm[j]]; } }}long long PHI(int N){ if (N<=1000000) return phi[N]%Mod; long long ans=N; for (int i=1;i<=prm[0];i++){ int v=prm[i]; if ((long long)v*v>N) break; if (N%v==0) ans=ans-ans/v; while (N%v==0) N/=v; if (N==1) break; } if (N!=1) ans=ans-ans/N; return ans%Mod;}long long F(int N){ long long h[5]; if (N<=2) return f[N+1]; memset(h,0,sizeof(h)); w.get(); w=powww(w,N-2); for (int i=1;i<=3;i++) for (int j=1;j<=3;j++) h[i]=(h[i]+mul(f[j],w.s[j][i]))%Mod; return h[3];}int main(){ get_prime(1000000); while (scanf("%d%d",&n,&m)!=EOF){ ans=0;Mod=(long long)m*n; f[1]=1;f[2]=1;f[3]=5; for (int i=1;i*i<=n;i++) if (n%i==0) if (i*i==n) ans=(ans+mul(PHI(i),F(i)))%Mod; else{ ans=(ans+mul(PHI(i),F(n/i)))%Mod; ans=(ans+mul(PHI(n/i),F(i)))%Mod; } ans=(ans+Mod)%Mod; ans=(ans/n)%m; printf("%I64d\n",ans); } return 0;}
- [HDU2481]Toy(置换+矩阵乘法)
- 【hdu2481】Toy,burnside引理+矩阵乘法
- hdu 2865 Birthday Toy (置换+DP+矩阵乘法)
- HDU2481:Toy(Burnside)
- hdu2481 Toy
- HDU2481 Toy (数论好题)
- poj 2888 Magic Bracelet (矩阵乘法+置换)
- 矩阵乘法经典应用之置换
- HDU 2865 Birthday Toy(Polya+矩阵乘法+dp)
- hdu2481
- [HDU2865]Birthday Toy(置换群+dp+矩乘)
- 置换矩阵(permutation matrix)
- 【codevs1287】矩阵乘法(矩阵乘法)
- 【codevs1287】矩阵乘法(矩阵乘法)
- 矩阵乘法(矩阵)【hpu】
- hdu4920(矩阵 乘法)
- 矩阵乘法(一)
- [POJ2888]Magic Bracelet(置换群+矩阵)
- linux文件查找命令(学习笔记)
- kruskal算法模板
- matplotlib 常用语句
- 浅谈对<xsl:apply-templates/>的理解
- 【连载】研究EasyUI系统— Messager组件
- [HDU2481]Toy(置换+矩阵乘法)
- 矩阵分类
- 多表查询
- 网友年龄
- 网站相似度有哪些手段去降低?
- (组队赛A/C)Gym
- hiho一下 第144周 机会渺茫 java
- 找出数组中出现次数超过一半的数
- 推荐系统的评价指标