• POJ 2888 Magic Bracelet ——Burnside引理


    【题目分析】

        同样是Burnside引理。但是有几种颜色是不能放在一起的。

        所以DP就好了。

        然后T掉

        所以矩阵乘法就好了。

        然后T掉

        所以取模取的少一些,矩阵乘法里的取模尤其要注意,就可以了。

        A掉

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define maxn 11
    #define ll long long 
    #define inf 0x3f3f3f3f
    #define maxm 100005
    const int md=9973;
    
    int T,n,m,k,ni,ispr[maxm],pr[maxm],top=0,sum;
    
    struct Matrix{
    	int x[maxn][maxn];
    	void init(){memset(x,0,sizeof x);}
    	void clear(){F(i,1,m)F(j,1,m)x[i][j]=1;}
    	void print()
    	{
    		F(i,1,m)
    		{
    			F(j,1,m) printf("%d ",x[i][j]);
    			printf("
    ");
    		}
    	}
    }A,B,C,D;
    
    Matrix operator * (const Matrix a,const Matrix b) {
    	Matrix c;
    	for (int i=1;i<maxn;++i)
    		for (int j=1;j<maxn;++j)
    		{
    			c.x[i][j]=0;
    			for (int k=1;k<maxn;++k)
    				c.x[i][j]+=a.x[i][k]*b.x[k][j];
    			c.x[i][j]%=md;
    		}
    	return c;
    }
    
    void init()
    {
    	F(i,2,maxm-1)
    	{
    		if (!ispr[i]) pr[++top]=i;
    		F(j,2,inf)
    		{
    			if (i*j>=maxm) break;
    			ispr[i*j]=1;
    		}
    	}
    }
    
    int qpow(int a,int b)
    {
    	int ret=1;a%=md;
    	while (b)
    	{
    		if (b&1) (ret*=a)%=md;
    		(a*=a)%=md;
    		b>>=1;
    	}
    	return ret;
    }
    
    int phi(int n)
    {
    	int ret=n;
    	for (int i=1;pr[i]*pr[i]<=n&&i<=top;++i)
    		if (n%pr[i]==0)
    		{
    			ret=ret-ret/pr[i];
    			while (n%pr[i]==0) n/=pr[i];
    		}
    	if (n>1) ret=ret-ret/n;
    	return ret%md;
    }
    
    int tak(int b)
    {
    	int ret=0;
    	D.init();F(i,1,m)D.x[i][i]=1;
    	C=B;
    	while (b)
    	{
    		if (b&1) D=D*C;
    		C=C*C;
    		b>>=1;
    	}
    	F(i,1,m) ret+=D.x[i][i];
    	return ret;
    }
    
    int main()
    {
    	init();
    	scanf("%d",&T);
    	while (T--)
    	{
    		sum=0;
    		scanf("%d%d%d",&n,&m,&k);
    		ni=qpow(n,md-2);
    		B.init();
    		B.clear();
    		F(i,1,k)
    		{
    			int a,b;
    			scanf("%d%d",&a,&b);
    			B.x[a][b]=B.x[b][a]=0;
    		}
    		for (int i=1;(ll)i*(ll)i<=(ll)n;++i)
    		{
    			if (n%i==0)
    			{
    				sum=(sum+tak(i)*phi(n/i))%md;
    				if (i*i!=n)
    					sum=(sum+tak(n/i)*phi(i))%md;
    			}
    		}
    		printf("%d
    ",(sum*ni)%md);
    	}
    }
    

      

  • 相关阅读:
    使用Atlas简化客户端Ajax编程(Atlas 介绍)
    CheckBoxList 的数据绑定及数据获取
    ASP.NET 中数据库操作初步
    弹出对话框的同时保持页面的显示
    .net中常用的命名空间解释
    Atlas—微软的Ajax工具包(初学者必看)
    链接数据库类 DB.CS
    顶贴个性图片生成
    推荐10多个优秀的设计资源的网站
    Linux基本命令大全
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6413768.html
Copyright © 2020-2023  润新知