思路挺清晰的。不过,我就是WA。不清楚为什么,很多数据都过了。

其实,一个置换后若有循环节个数为K,则N必定可以除以尽K。而K正好可以看成一个环。为什么呢?看前K个珠子,就是一个环,而后面的若干个K个珠子,不过就是不停的重复而已。这样,循环节的个数可以由最大公约数求得。那么,这个K个珠子构成的环符合题意的有多少种呢?很巧妙的一个方法是,用矩阵表示,若颜色相邻则I,J可以为1,否则为0。矩阵相乘有一个应用就是求的路径数啊。

最后,求逆元即可。可我的就是不过,求大神路过时指点。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define MOD 9973
using namespace std; struct Matrix{
int m[12][12];
}mat[50];
int m;
bool isprime[35000];
int prime[35000],np;
int dive[100],dn; Matrix operator * (Matrix a,Matrix b){
Matrix ret;
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
ret.m[i][j]=0;
for(int k=1;k<=m;k++){
ret.m[i][j]=(ret.m[i][j]+(a.m[i][k]*b.m[k][j])%MOD)%MOD;
}
}
}
return ret;
}
void getprime(){
memset(isprime,true,sizeof(isprime));
np=0;
for(int i=2;i<35000;i++){
if(isprime[i]){
prime[np++]=i;
for(int j=i*i;j<35000;j+=i){
isprime[j]=false;
}
}
}
} void divn(int n){
dn=0;
int L =(int)sqrt(n*1.0);
for(int i=1;i<=L;i++){
if(n%i==0){
dive[dn++]=i;
if(i!=n/i)
dive[dn++]=n/i;
}
}
} void getinit(){
for(int i=1;i<50;i++){
mat[i]=mat[i-1]*mat[i-1];
}
} int phi(int p){
int n=p;
int res=p;
for(int i=0;i<np&&prime[i]*prime[i]<=n;i++){
if(p%prime[i]==0){
res=res-res/prime[i];
while(p%prime[i]==0)
p/=prime[i];
}
}
if(p>1)
res=res-res/p;
return res%MOD;
} int quick(int b){
Matrix ans;
memset(ans.m,0,sizeof(ans.m));
for(int i=1;i<=m;i++)
ans.m[i][i]=1;
int k=0;
while(b){
if(b&1) ans=ans*mat[k];
b>>=1;
k++;
}
int res=0;
for(int i=1;i<=m;i++)
res=(res+ans.m[i][i])%MOD;
return res;
} void exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1;
y=0;
return ;
}
exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
} void slove(int n,int m){
int x,y;
exgcd(n,MOD,x,y);
int ans=0;
for(int i=0;i<dn;i++){
ans=(ans+(phi(n/dive[i])%MOD)*quick(dive[i]))%MOD;
}
x=(x%MOD+MOD)%MOD;
ans=(ans*x)%MOD;
printf("%d\n",ans);
} int main(){
int n,k,p,q,T;
getprime();
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++)
mat[0].m[i][j]=1;
}
for(int i=1;i<=k;i++){
scanf("%d%d",&p,&q);
mat[0].m[p][q]=mat[0].m[q][p]=0;
}
getinit();
divn(n);
slove(n,m);
}
return 0;
}

  以下是别人的代码:http://blog.csdn.net/tmeteorj/article/details/8654330

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int mr=100000;
const LL mod=9973;
bool notp[mr];
int pr[mr],fac[102],num[102];
int pn,top,n,m;
LL ans;
struct MAT
{
LL bas[13][13];
void init()
{
memset(bas,0,sizeof(bas));
}
} mat[50];
MAT mul(MAT a,MAT b)
{
MAT c;
c.init();
for(int i=1; i<=m; i++)
for(int k=1; k<=m; k++)
{
if(a.bas[i][k])
{
for(int j=1; j<=m; j++)
{
c.bas[i][j]+=a.bas[i][k]*b.bas[k][j];
if(c.bas[i][j]>=mod)
c.bas[i][j]%=mod;
}
}
}
return c;
}
void getpri()//筛素数
{
pn=0;
memset(notp,0,sizeof(notp));
for(int i=2; i<mr; i++)
{
if(!notp[i])
{
pr[pn++]=i;
}
for(int j=0; j<pn && i*pr[j]<mr; j++)
{
int k=i*pr[j];
notp[k]=1;
if(i%pr[j]==0)break;
}
}
}
void divn()
{
int nn=n;
top=0;
int lim=(int)sqrt((double(nn)))+1;
for(int i=0; pr[i]<=lim; i++)
{
if(nn%pr[i]==0)
{
fac[top]=pr[i];
num[top]=0;
while(nn%pr[i]==0)
num[top]++,nn/=pr[i];
top++;
}
}
if(nn>1)
fac[top]=nn,num[top++]=1;
}
int phi(int x)
{
int i, res=x;
for (i=0;pr[i]<(int)sqrt((double)x)+1;i++)
if(x%pr[i]==0)
{
res=res/pr[i]*(pr[i]-1);
while(x%pr[i]==0)x/=pr[i];
}
if(x>1)res=res/x*(x-1);
return res;
}
void solve(int r)
{
int res=phi(n/r);
MAT mt;
mt.init();
for(int i=1;i<=m;i++)
mt.bas[i][i]=1;
for(int i=1,tp=r;tp;i++,tp>>=1)
if(tp&1)mt=mul(mt,mat[i]);
for(int i=1;i<=m;i++)
{
ans+=mt.bas[i][i]*res;
if(ans>=mod)ans%=mod;
}
}
void dfs(int id,int sum)
{
if(id==top)
{
solve(sum);
return;
}
else
{
dfs(id+1,sum);
for(int ct=0; ct<num[id]; ct++)
dfs(id+1,sum=sum*fac[id]);
}
}
void init()
{
for(int i=2; i<50; i++)
mat[i]=mul(mat[i-1],mat[i-1]);
}
int Egcd (int a,int b, int &x, int &y)
{
if (b==0)
{
x=1,y=0;
return a;
}
LL d, tp;
d = Egcd (b, a%b, x, y);
tp = x;
x = y;
y = tp - a/b*y;
return d;
}
int getni()
{
int x,y;
Egcd(n,mod,x,y);
return (x%mod+mod)%mod;
}
int main()
{
getpri();
int T;
for(scanf("%d",&T); T; T--)
{
int k;
scanf("%d%d%d",&n,&m,&k);
ans=0;
for(int i=1; i<=m; i++)
for(int j=1; j<=m; j++)
mat[1].bas[i][j]=1;
for(int a,b,i=0; i<k; i++)
{
scanf("%d%d",&a,&b);
mat[1].bas[a][b]=mat[1].bas[b][a]=0;
}
init();
divn();
dfs(0,1);
printf("%d\n",ans*getni()%mod);
}
return 0;
}

  

POJ 2888的更多相关文章

  1. poj 2888 Magic Bracelet(Polya+矩阵快速幂)

    Magic Bracelet Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 4990   Accepted: 1610 D ...

  2. poj 2888 Magic Bracelet <polya定理>

    题目:http://poj.org/problem?id=2888 题意:给定n(n <= 10^9)颗珠子,组成一串项链,每颗珠子可以用m种颜色中一种来涂色,如果两种涂色方法通过旋转项链可以得 ...

  3. POJ 2888 Magic Bracelet(Burnside引理,矩阵优化)

    Magic Bracelet Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 3731   Accepted: 1227 D ...

  4. poj 2888 Magic Bracelet

    经典的有限制条件的Burnside计数+矩阵乘法!!! 对于这种限制条件的情况我们可以通过矩阵连乘得到,先初始化矩阵array[i][j]为1.如果颜色a和颜色b不能涂在相邻的珠子, 那么array[ ...

  5. POJ 2888 Magic Bracelet(burnside引理+矩阵)

    题意:一个长度为n的项链,m种颜色染色每个珠子.一些限制给出有些颜色珠子不能相邻.旋转后相同视为相同.有多少种不同的项链? 思路:这题有点综合,首先,我们对于每个n的因数i,都考虑这个因数i下的不变置 ...

  6. POJ 2888 Magic Bracelet [Polya 矩阵乘法]

    传送门 题意:竟然扯到哈利波特了.... 和上一题差不多,但颜色数很少,给出不能相邻的颜色对 可以相邻的连边建图矩阵乘法求回路个数就得到$f(i)$了.... 感觉这样的环上有限制问题挺套路的...旋 ...

  7. 解题:POJ 2888 Magic Bracelet

    题面 这题虽然很老了但是挺好的 仍然套Burnside引理(因为有限制你并不能套Polya定理),思路和这个题一样,问题主要是如何求方案. 思路是把放珠子的方案看成一张图,然后就巧妙的变成了一个经典的 ...

  8. POJ 2888 Magic Bracelet ——Burnside引理

    [题目分析] 同样是Burnside引理.但是有几种颜色是不能放在一起的. 所以DP就好了. 然后T掉 所以矩阵乘法就好了. 然后T掉 所以取模取的少一些,矩阵乘法里的取模尤其要注意,就可以了. A掉 ...

  9. [POJ 2888]Magic Bracelet[Polya Burnside 置换 矩阵]

    也许更好的阅读体验 \(\mathcal{Description}\) 大意:给一条长度为\(n\)的项链,有\(m\)种颜色,另有\(k\)条限制,每条限制为不允许\(x,y\)颜色连在一起.要求有 ...

随机推荐

  1. 【C/C++多线程编程之十】pthread线程私有数据

    多线程编程之线程私有数据      Pthread是 POSIX threads 的简称.是POSIX的线程标准.         线程同步从相互排斥量[C/C++多线程编程之六]pthread相互排 ...

  2. 不做Next,争做Nest——庆科首届智能硬件创新设计大赛产生决赛12强

      智能硬件,Wi-Fi互联,谁是下一个Nest?邀你共见证! 2014年3月到7月.由上海庆科信息技术有限公司主办的首届 MXCHIP 智能硬件创新设计大赛--"寻找下一个nest&quo ...

  3. OpenST Basic tool library

    /***************************************************************************** * OpenST Basic tool l ...

  4. 创建cifs系统案例之“实现将Windows磁盘共享至Linux”

    原创作品,出自 "深蓝的blog" 博客,欢迎转载,转载时请务必注明出处,否则追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlong ...

  5. YunOS曙光初现----看好阿里云OS----阿冬专栏!!

    阿里云os - YunOS 阿里云OS(YunOS)是阿里巴巴集团的智能手机操作系统,依托于阿里巴巴集团电子商务领域积累的经验和强大的云计算平台,基于LINUX开发. 魅族4阿里yun OS版已上市. ...

  6. tp中使用事务

    是什么 事务是为了防止,多个操作,其中有失败,数据有部分被执行成功的时候使用的. 比如,银行,用户转账.张三钱扣了,结果李四钱还增加! 这个时候需要使用事务,确保张三钱扣了,李四的钱也增加,才真正的成 ...

  7. CodeForces--609C --Load Balancing(水题)

    Load Balancing Time Limit: 2000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64u Subm ...

  8. 9. Palindrome Number[E]回文数

    题目 Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same b ...

  9. 自动化框架的两种断言设计(pytest 版)

    自动化测试断言失败时,根据不同业务场景,可能需要立即终止或继续执行.这里以 Appium + pytest 为例. 一. 断言失败立即终止 用途一:用例的预期结果是其他用例的前提条件时,assert ...

  10. python包管理(distutils、easy_install、pip、setup.py/requirements.txt、wheel)

    distutils.distutils2 distutils是 python 标准库的一部分,2000年发布.使用它能够进行 python 模块的 安装 和 发布. distutils2 被设计为 d ...