Birthday Toy HDU

来源:互联网 发布:广州白云行知职业技术学校 编辑:程序博客网 时间:2024/06/06 09:10

题意:

给这样的一个玩具涂k种颜色,线连接的不能颜色相同,有多少个

思路:

像 Magic Bracelet一样的题,只是这一次不同的是相邻的不能同色

我们先安排一个颜色给中间那个,剩下k-1种颜色去涂外面那个圈,相邻不能一个颜色


1)从邻接矩阵出发我们建立一个每个元素都是1,对角线都是0的矩阵,长度为n的原串就是矩阵开n方后,

sigma a[i][i] 就是方案数


2)或者我们可以找找规律

n=1     f(1)=0

n=2     f(2)=k(k-1)

n=3     f(3)=k(k-1)(k-2)

n=4     f(4)=k(k-1) *(1*(k-1) + (k-2)(k-2)     )


f(n)=f(n-1)*(k-2) + f(n-2)*(k-1)

可以用快速幂来求

#include<iostream>#include<string.h>#include<stdio.h>#define ll int#define mod  9973using namespace std;struct node{ll a[10][10];};node A;node B;int n,m;node cheng(node a,node b){node c;memset(c.a,0,sizeof(c.a));for(int i=0;i<m;i++)for(int j=0;j<m;j++)for(int k=0;k<m;k++)if(a.a[i][k]&&b.a[k][j])c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;return  c;}ll s(ll n){node x=A;node y=B;while(n){if(n&1) y=cheng(y,x);x=cheng(x,x);n>>=1;}   ll num=0;   for(int i=0;i<m;i++)    num=(num+y.a[i][i])%mod;     return num; }ll qpow(ll a,ll b){ll ans=1;a%=mod;while(b){if(b&1) ans=(ans*a)%mod;;a=(a*a)%mod;b>>=1;}return ans;}ll euler(ll n){ll res=n;for(int i=2;i*i<=n;i++){if(n%i==0){res/=i;res*=(i-1);while(n%i==0) n/=i;}}if(n>1) {res/=n;res*=(n-1);}return res%mod;}ll solve(){   ll ans=0;      for(ll i=1;i*i<=n;i++)   {   if(n%i==0)   {      ans=(ans+euler(n/i)*s(i))%mod;  //euler(n/i) gcd=i 的个数     gcd为循环节个数    if(i*i!=n)   ans=(ans+euler(i)*s(n/i))%mod;      }   }   return (ans*qpow(n,mod-2))%mod;}int main(){int T;int k,a,b;cin>>T;memset(B.a,0,sizeof(B.a));for(int i=0;i<10;i++)B.a[i][i]=1;while(T--){   scanf("%d%d%d",&n,&m,&k);for(int i=0;i<m;i++)for(int j=0;j<m;j++)A.a[i][j]=1;for(int i=0;i<k;i++){scanf("%d%d",&a,&b);A.a[a-1][b-1]=A.a[b-1][a-1]=0;}printf("%d\n",solve());}return 0;}