题意:
一个n个节点的环,可以涂m中不同的颜色,但是有k对颜色是不能相邻的。现在问有多少种涂法。
题解:
这题我们枚举gcd(n,i)=k,判断有多少个i满足k统一计算,相当于求n/k的欧拉函数,对于k对颜色无法相邻的这个限制,我们将能相邻的定义成关系矩阵,这样k次幂后就能计算出对应的不懂置换的个数,接着用容斥处理欧拉函数,或者用欧拉定理求。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> #include<stack> #include<string> #define B(x) (1<<(x)) using namespace std; typedef long long ll; void cmax(int &a,int b){ if(b>a)a=b; } void cmin(int &a,int b){ if(b<a)a=b; } void cmax(ll &a,ll b){ if(b>a)a=b; } void cmin(ll &a,ll b){ if(b<a)a=b; } void add(int &a,int b,int mod){ a=(a+b)%mod; } void add(ll &a,ll b,ll mod){ a=(a+b)%mod; } void add(int &a,int b){ a+=b; } void add(ll &a,ll b){ a+=b; } const int oo=0x3f3f3f3f; const ll MOD=9973; const int maxn = 15; int fac[1000000],cnt; int prime[100000],p; struct MAZE{ int maze[maxn][maxn]; int n; MAZE(){ n=0;} MAZE(int n_){ memset(maze,0,sizeof maze); n=n_; } MAZE operator*(const MAZE &a)const{ MAZE b(n); for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ if(maze[i][k]==0)continue; for(int j=1;j<=n;j++){ b.maze[i][j]+=maze[i][k]*a.maze[k][j]%MOD; if(b.maze[i][j]>=MOD) b.maze[i][j]-=MOD; } } } return b; } void ONE(){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) maze[i][j]=1; } }; MAZE maze_pow(MAZE a,int k){ MAZE b(a.n); for(int i=1;i<=a.n;i++)b.maze[i][i]=1; while(k){ if(k&1) b=b*a; a=a*a; k>>=1; } return b; } void get_fac(int n){ cnt=0; for(int i=1;(ll)i*i<=n;i++){ if(n%i==0){ fac[cnt++]=i; if(n/i!=i) fac[cnt++]=n/i; } } } int dfs(int s,int x){ int res=0; for(int i=s;i<p;i++){ res+=x/prime[i]-dfs(i+1,x/prime[i]); } return res; } int Count(int n){ p=0; int m=n; for(int i=2;(ll)i*i<=n;i++){ if(n%i==0){ prime[p++]=i; while(n%i==0) n/=i; } } if(n>1&&prime[p-1]!=n)prime[p++]=n; return (m-dfs(0,m))%MOD; } int ex_gcd(int a,int b,int &x,int &y){ if(b==0){ x=1; y=0; return a; } int d=ex_gcd(b,a%b,x,y); int t=x; x=y; y=t-a/b*y; return d; } int main(){ int T,n,m,k,u,v; scanf("%d",&T); while(T--){ scanf("%d %d %d",&n,&m,&k); MAZE ans(m),a(m); a.ONE(); for(int i=1;i<=k;i++){ scanf("%d %d",&u,&v); a.maze[u][v]=a.maze[v][u]=0; } get_fac(n); ll res=0; for(int i=0;i<cnt;i++){ ll temp=0; ans=maze_pow(a,fac[i]); for(int i=1;i<=m;i++){ temp+=ans.maze[i][i]; if(temp>=MOD) temp-=MOD; } res+=temp*Count(n/fac[i]); if(res>=MOD) res-=MOD; } int x=0,y=0; ex_gcd(n,MOD,x,y); x=(x%MOD+MOD)%MOD; cout<<res*x%MOD<<endl; } return 0; }