zoukankan      html  css  js  c++  java
  • LG4980 【模板】Polya定理 和 BZOJ2026 宝石纪念币

    题意

    题目描述

    给定一个$n$个点,$n$条边的环,有$n$种颜色,给每个顶点染色,问有多少种本质不同的染色方案,答案对$10^9+7$取模

    注意本题的本质不同,定义为:只需要不能通过旋转与别的染色方案相同

    输入输出格式

    输入格式:

    第一行输入一个$t$,表示有$t$组数据

    第二行开始,一共$t$行,每行一个整数$n$,意思如题所示。

    输出格式:

    共$t$行,每行一个数字,表示染色方案数对$10^9+7$取模后的结果

    输入输出样例

    输入样例#1: 复制
    5
    1 
    2 
    3 
    4 
    5 
    输出样例#1: 复制
    1
    3
    11
    70
    629

    说明

    $$n leq 10^9$$ $$t leq 10^3$$

    分析

    先找不动点个数公式。考虑循环移动(i)位这个置换,把珠子循环编号。由于移动后编号要重复,所以最大的编号一定是( extrm{lcm}(i,m))。所以一个循环里面的珠子个数就是(frac{ extrm{lcm}(i,m)}{i}=frac{n}{gcd(i,n)})。所以共有(gcd(i,n))个循环。因此不动点个数是(n^{gcd(i,n)})

    所以答案式为

    [frac 1nsum_{i=0}^{n-1}n^{gcd(i,n)} \ =frac 1nsum_{d|n}varphi(frac nd)n^d \ =sum_{d|n}varphi(d) n^{frac nd-1} ]

    我并不知道先枚约数再算欧拉函数的复杂度是多少,反正约数个数怎么也达不到(O(sqrt{n}))的上界。
    即使(2^3*3*5*7*11*13*17*19*23=892371480),这个数也只有1024个约数,小于(sqrt{892371480}=29872.587433)

    int phi(int n){
    	int re=n;
    	for(int i=2;i*i<=n;++i)if(n%i==0){
    		re=re/i*(i-1);
    		while(n%i==0) n/=i;
    	}
    	if(n>1) re=re/n*(n-1);
    	return re;
    }
    void Polya(){
    	int n=read<int>(),ans=0;
    	for(int i=1;i*i<=n;++i)if(n%i==0){
    		ans=add(ans,mul(phi(i),fpow(n,n/i-1)));
    		if(i*i!=n) ans=add(ans,mul(phi(n/i),fpow(n,i-1)));
    	}
    	printf("%d
    ",ans);
    }
    int main(){
    //	freopen("LG4980.in","r",stdin),freopen("LG4980.out","w",stdout);
    	for(int t=read<int>();t--;) Polya();
    	return 0;
    }
    

    宝石纪念币

    跟上面那道题一样。不过多了些要求:共17中颜色,每种都要用上。保留120位数。

    那么简单容斥,并实现高精度即可。

    https://cyaron.blog.luogu.org/solution-p2162

    我果然写不来高精度……算是做个高精练习吧。

    不想容斥的话也可以用矩阵乘法:https://www.cnblogs.com/ccz181078/p/7122566.html?utm_source=itdadao&utm_medium=referral

    CO int mod=1e9;int n; // qn+r
    inter node(int x){
    	inter a(15);
    	a[0]=x%n,a[1]=x/n;
    	return a;
    }
    inter operator+(CO inter&a,CO inter&b){
    	inter ans(15);
    	ans[0]=a[0]+b[0];
    	if(ans[0]>=n) ++ans[1],ans[0]-=n;
    	for(int i=1;i<=14;++i){
    		ans[i]+=a[i]+b[i];
    		if(ans[i]>=mod){
    			if(i+1<=14) ++ans[i+1];
    			ans[i]-=mod;
    		}
    	}
    	return ans;
    }
    inter operator-(CO inter&a,CO inter&b){ // a>=b
    	inter ans(15);
    	ans[0]=a[0]-b[0];
    	if(ans[0]<0) --ans[1],ans[0]+=n;
    	for(int i=1;i<=14;++i){
    		ans[i]+=a[i]-b[i];
    		if(ans[i]<0){
    			if(i+1<=14) --ans[i+1];
    			ans[i]+=mod;
    		}
    	}
    	return ans;
    }
    inter operator*(CO inter&a,CO inter&b){
    	vector<int128> ans(15);
    	ans[0]=(int128)a[0]*b[0]; 
    	ans[1]+=ans[0]/n,ans[0]%=n;
    	for(int i=1;i<=14;++i){
    		ans[i]+=(int128)a[i]*b[0]+(int128)a[0]*b[i];
    		for(int j=1;j<=i;++j) ans[i]+=(int128)a[j]*b[i+1-j]*n;
    		if(i+1<=14) ans[i+1]+=ans[i]/mod;
    		ans[i]%=mod;
    	}
    	return inter(ans.begin(),ans.end());
    }
    inter pow(inter a,int b){
    	inter ans(15);ans[0]=1;
    	for(;b;b>>=1,a=a*a)
    		if(b&1) ans=ans*a;
    	return ans;
    }
    
    int phi(int n){
    	int ans=n;
    	for(int i=2;i*i<=n;++i)if(n%i==0){
    		ans=ans/i*(i-1);
    		while(n%i==0) n/=i;
    	}
    	if(n>1) ans=ans/n*(n-1);
    	return ans;
    }
    
    int C[20][20];
    
    int main(){
    	read(n);
    	if(n<17){
    		for(int i=1;i<=120;++i) putchar('0');
    		puts("");
    		return 0;
    	}
    	for(int i=0;i<=17;++i){
    		C[i][0]=C[i][i]=1;
    		for(int j=1;j<i;++j) C[i][j]=C[i-1][j-1]+C[i-1][j];
    	}
    	inter ans(15);
    	for(int d=1;d*d<=n;++d)if(n%d==0){
    		inter sum(15);
    		for(int i=1;i<=17;i+=2) sum=sum+node(C[17][i])*pow(node(i),d);
    		for(int i=2;i<=17;i+=2) sum=sum-node(C[17][i])*pow(node(i),d);
    		sum=sum*node(phi(n/d));
    		ans=ans+sum;
    		if(n/d==d) continue;
    		sum=node(0);
    		for(int i=1;i<=17;i+=2) sum=sum+node(C[17][i])*pow(node(i),n/d);
    		for(int i=2;i<=17;i+=2) sum=sum-node(C[17][i])*pow(node(i),n/d);
    		sum=sum*node(phi(d));
    		ans=ans+sum;
    	}
    	printf("%03d",ans[14]%1000); // edit 1
    	for(int i=13;i>=1;--i) printf("%09d",ans[i]);
    	puts("");
    	return 0;
    }
    
  • 相关阅读:
    最优化方法(无约束)转载
    启动eclipse,弹出提示:java was started but returned exit code = 13
    前端开发之div实现table表格系列教程三:参数说明
    前端开发之div实现table表格系列教程二:拖动表格draggable
    前端开发之div实现table表格系列教程一:创建表格
    前端开发之弹出框系列教程十:通用参数说明
    前端开发之弹出框系列教程九:动画
    前端开发之弹出框系列教程八:自定义按钮栏
    前端开发之弹出框系列教程七:父页面与子窗口交互
    前端开发之弹出框系列教程六:win打开新窗口
  • 原文地址:https://www.cnblogs.com/autoint/p/10689584.html
Copyright © 2011-2022 走看看