思路挺清晰的。不过,我就是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. 洛谷—— P1204 [USACO1.2]挤牛奶Milking Cows

    https://www.luogu.org/problem/show?pid=1204 题目描述 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶.第一个农民在300秒(从5点开始计时)给他的牛挤奶, ...

  2. Zookeeper源代码编译为Eclipseproject(win7下Ant编译)

    为了深入学习ZooKeeper源代码,首先就想到将其导入到Eclispe中,所以要先将其编译为Eclispeproject. 1.什么是Ant??? Apache Ant™ Apache Ant is ...

  3. 菜鸟的mongoDB学习---(六)MongoDB 索引

    MongoDB 索引 ps:大概有半个月木有更新了,因为前一阶段的出差和这几天突然来的项目.导致上网时间急剧降低,实在是sorry,以后预计会好一点. 索引通常可以极大的提高查询的效率.假设没有索引. ...

  4. 2014秋C++ 第7周项目 数据类型和表达式

    课程主页在http://blog.csdn.net/sxhelijian/article/details/39152703,课程资源在云学堂"贺老师课堂"同步展示,使用的帐号请到课 ...

  5. iOS_自己定义毛玻璃效果

    终于效果图: 关键代码: UIImage分类代码 // // UIImage+BlurGlass.h // 帅哥_团购 // // Created by beyond on 14-8-30. // C ...

  6. 2015.04.21,外语,读书笔记-《Word Power Made Easy》 12 “如何奉承朋友” SESSION 32

    TEASER PREVIEW 如何描述这些人: 很友好.容易相处的人: 不知疲倦的人: 简单.直率..aboveboard([ə'bʌv'bɔ:d] adv. 光明正大地, 率直地 adj. 光明正大 ...

  7. js中的三种函数写法

    js中的三种函数写法 <script type="text/javascript"> //普通的声明方式 function myFun(m,n){ alert(m+n) ...

  8. AngularJS 下拉列表demo

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script sr ...

  9. ActiveX插件

    C#制作ActiveX插件 首先新建项目--->类库,取名:ActiveXDemo 右键项目属性:应用属性==>程序集信息=>使程序集Com可见, 生成==>输出==>为 ...

  10. vue.js的学习之路

    因为对jquery的ajax渲染很不满,所以我就来学vue.js了 1)vue.js是什么 官方解释为:Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型 ...