【POJ2888】Magic Bracelet-Burnside引理+数论+DP矩阵优化
来源:互联网 发布:c语言fprintf 编辑:程序博客网 时间:2024/06/07 08:20
测试地址:Magic Bracelet
题目大意:要用
做法:这题非常经典,思路很有代表性,是进阶Burnside引理和Polya定理题的一块敲门砖,需要用到:Burnside引理,欧拉函数,DP+矩阵快速幂,乘法逆元。
首先一看题目是计数,就自然而然地联想到Burnside引理和Polya定理,然而这题有不能相邻的条件,所以不能直接用Polya定理,那么我们考虑使用Burnside引理来解决。
我们知道环形的旋转置换有
但是最后一个元素的填色除了和它前一个元素有关,还和第一个元素有关,那么这个状态转移方程是不是错的呢?实际上,我们只需一开始枚举第一个元素的颜色
上面的方法的时间复杂度是
首先优化计算Burnside公式的时间复杂度。我们知道
接下来优化DP的时间复杂度,注意到
经过了以上两个优化,外层枚举的复杂度降到差不多
以下是本人代码:
#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#define ll long longusing namespace std;ll n,ans;int T,m,k;struct matrix {ll s[11][11];} M[40];void exgcd(ll a,ll b,ll &x,ll &y){ ll x0=1,y0=0,x1=0,y1=1; while(b) { ll tmp,q; q=a/b; tmp=x0,x0=x1,x1=tmp-q*x1; tmp=y0,y0=y1,y1=tmp-q*y1; tmp=a,a=b,b=tmp%b; } x=x0,y=y0;}matrix mult(matrix A,matrix B){ matrix S; memset(S.s,0,sizeof(S.s)); for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) for(int k=1;k<=m;k++) S.s[i][j]=(S.s[i][j]+A.s[i][k]*B.s[k][j])%9973; return S;}matrix power(ll x){ int i=0; matrix S; memset(S.s,0,sizeof(S.s)); for(int j=1;j<=m;j++) S.s[j][j]=1; while(x) { if (x&1) S=mult(S,M[i]); i++;x>>=1; } return S;}ll phi(ll x){ ll s=x; for(ll i=2;i*i<=x;i++) if (!(x%i)) { s=s/i*(i-1); while(!(x%i)) x/=i; } if (x>1) s=s/x*(x-1); return s;}void solve(ll x){ matrix S=power(x); ll sum=0; for(int i=1;i<=m;i++) sum=(sum+S.s[i][i])%9973; sum=(sum*phi(n/x))%9973; ans=(ans+sum)%9973;}int main(){ scanf("%d",&T); while(T--) { scanf("%lld%d%d",&n,&m,&k); ans=0; memset(M[0].s,0,sizeof(M[0].s)); for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) M[0].s[i][j]=1; for(int i=1,a,b;i<=k;i++) { scanf("%d%d",&a,&b); M[0].s[a][b]=M[0].s[b][a]=0; } for(int i=1;i<=35;i++) M[i]=mult(M[i-1],M[i-1]); for(ll i=1;i*i<=n;i++) if (n%i==0) { solve(i); if (i!=n/i) solve(n/i); } ll x0,y0; exgcd(n,9973,x0,y0); x0=(x0%9973+9973)%9973; printf("%lld\n",(x0*ans)%9973); } return 0;}
- 【POJ2888】Magic Bracelet-Burnside引理+数论+DP矩阵优化
- [POJ2888]Magic Bracelet(置换群+矩阵)
- poj2888 Magic Bracelet
- poj 2888 Magic Bracelet 置换(Burnside引理)+矩阵
- 【HDU2865】Birthday Toy-Burnside引理+数论+DP矩阵优化
- POJ 2888 Magic Bracelet (Burnside , 矩阵幂 )
- POJ 2888 Magic Bracelet(Burnside引理+欧拉函数+矩阵快速幂+逆元)
- POJ 2888 Magic Bracelet (有限制的Burnside引理)
- Poj 2888 & Hoj 2722 Magic Bracelet (有限制的Burnside 矩阵性质 欧拉函数)
- POJ-2888-Magic Bracelet-Burnside&&polay计数
- 【HDU2865】构造矩阵+Burnside定理+欧拉函数类似poj2888
- POJ 2888 Magic Bracelet(Polya计数+dp+矩阵快速幂+欧拉函数+乘法逆元)
- poj 2888 Magic Bracelet (polya,矩阵)
- POJ 2888 Magic Bracelet (经典Polya+矩阵)
- POJ 2888 Magic Bracelet (Polya+欧拉函数+矩阵乘法)
- poj 2888 Magic Bracelet polya计数+矩阵统计路径数
- POJ 2888 Magic Bracelet(polya+矩阵快速幂)
- poj 2888 Magic Bracelet (矩阵乘法+置换)
- 多线程之互斥锁(By C++)与多进程
- 实验三 Huffman编解码算法实现与压缩效率分析
- 人脸识别--活体检测(眨眼检测)
- Centos 配置hostonly网络 使用winscp与服务器主机互联
- es6-symbol
- 【POJ2888】Magic Bracelet-Burnside引理+数论+DP矩阵优化
- java 转发和重定向
- RISC-V学习第一篇
- Getting Started with the LLVM System
- iOS应用内支付(IAP)详解
- 论文写作中常用工具和格式排版
- Getting Started: Building and Running Clang
- Mac下Appium环境搭建
- MOOC北京理工《C语言程序设计(上)》第8周第2题:寻找矩阵的鞍点