【置换群】【枚举约数】hdu6038 Function

把b数组的所有置换群求出来,用数组记录一下每个大小所出现的次数。

然后求a的置换群,对每个置换群求能被其整除的b的置换群的大小总和(只有这些才能满足构造出一个f,且不自相矛盾),然后把它们全都乘起来就是答案。

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
#define MOD 1000000007ll
int n,m,a[100010],b[100010],zu;
bool vis[100010];
//ll Quick_Pow(ll a,ll p){
//	if(!p){
//		return 1;
//	}
//	ll res=Quick_Pow(a,p>>1);
//	res=res*res%MOD;
//	if(p&1ll){
//		res=(a%MOD*res)%MOD;
//	}
//	return res;
//}
int nowsiz,cnts[100010];
void dfs(int U){
	vis[U]=1;
	++nowsiz;
	if(!vis[b[U]]){
		dfs(b[U]);
	}
}
void df2(int U){
	vis[U]=1;
	++nowsiz;
	if(!vis[a[U]]){
		df2(a[U]);
	}
}
int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		memset(cnts,0,sizeof(cnts));
		++zu;
		for(int i=0;i<n;++i){
			scanf("%d",&a[i]);
		}
		for(int i=0;i<m;++i){
			scanf("%d",&b[i]);
		}
		for(int i=0;i<m;++i){
			if(!vis[i]){
				nowsiz=0;
				dfs(i);
				++cnts[nowsiz];
			}
		}
		memset(vis,0,sizeof(bool)*m);
		ll ans=1;
		for(int i=0;i<n;++i){
			if(!vis[i]){
				nowsiz=0;
				df2(i);
				int allcanb=0;
				for(int i=1;i*i<=nowsiz;++i){
					if(nowsiz%i==0){
						if(i*i==nowsiz){
							allcanb+=cnts[i]*i;
						}
						else{
							allcanb+=cnts[i]*i;
							allcanb+=cnts[nowsiz/i]*(nowsiz/i);
						}
					}
				}
				ans=ans*(ll)allcanb%MOD;
			}
		}
		printf("Case #%d: %lld\n",zu,ans);
		memset(vis,0,sizeof(bool)*n);
	}
	return 0;
}
时间: 2024-10-21 21:16:03

【置换群】【枚举约数】hdu6038 Function的相关文章

【数论】【枚举约数】【友好数】CODEVS 2632 非常好友

O(sqrt(n))枚举约数,根据定义暴力判断友好数. 1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 int n; int limit; 5 int main() 6 { 7 scanf("%d",&n); 8 for(;;n++) 9 { 10 limit=sqrt(n); int tot=1; 11 if(limit*limit==n) tot+=limit; 12 for

【数论】【最大公约数】【枚举约数】CODEVS 1012 最大公约数和最小公倍数问题 2001年NOIP全国联赛普及组

对于一对数(p,q),若它们的gcd为x0,lcm为y0, 则:p*q/x0=y0,即q=x0*y0/p, 由于p.q是正整数,所以p.q都必须是x0*y0的约数. 所以O(sqrt(x0*y0))地枚举约数,依次用gcd判断. 1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 typedef long long LL; 5 LL limit,Q,P,To; 6 int ans; 7 LL gcd(LL a,

【数论】【枚举约数】【欧拉函数】bzoj2705 [SDOI2012]Longge的问题

∵∑gcd(i, N)(1<=i <=N) =k1*s(f1)+k2*s(k2)+...+km*s(km) {ki是N的约数,s(ki)是满足gcd(x,N)=ki(1<=x<=N)的x的个数} ∴gcd(x,N)=ki (1<=x<=N)  <=>  gcd(x/ki,N/ki)=1 (1<=x/ki<=N/ki) gcd(x/ki,N/ki)=1 (1<=x/ki<=N/ki) 的x的个数 即为φ(N/ki) ∴ans=∑φ(N/

hdu4983 / 枚举约数+欧拉函数

求满足 gcd(a,n)*acd(b,n)=n^k的整数对(a,b).n<=10^9 特殊情况考虑一下(n=1,k>=2),问题很容易转化为求euter(n/g)*euter(g),g是约数.这题比赛时候竟然应该不会求n的约数二不会做! 求约数时候,枚举(1,根号n),另一半对应啊!欧拉函数,这次有改进. #include<iostream> #include<cstdio> #include<cmath> using namespace std; long

最高科技——快速枚举约数

求数\(n\)的最小的约数\(r\),使\(r\)满足性质\(P\),这些性质满足这样的一个条件:若有\(d|r\)满足性质\(P\),则有\(r\)也满足\(P\). 首先\(O(\sqrt{n})\)直接暴力枚举因数显然可行,然而我们有更快的方法. 设\(n=p_1^{k_1}p_2^{k_2}\ldots p_m^{k_m}\) 我们先从大到小枚举数\(w_1\),使其成为最小的\(w_1\)使得\(t=p_1^{w_1}p_2^{k_2}\ldots p_m^{k_m}\)满足\(P\)

【枚举约数】Gym - 101412A - Ginkgo Numbers

给你一堆定义,问你在那个定义下,<p,q>是不是素数.其实那堆定义都不用管,只要看最下面给你的提示即可. 根据,只要把m^2+n^2当一个整体,去枚举(p^2+q^2)的约数即可,然后再枚举m, 这样的枚举出来是必要的,然后再根据这个充要条件判一下即可. #include<cstdio> #include<cmath> using namespace std; const double EPS=0.00000001; int T; int p,q; bool check

【枚举约数】HackerRank - Week of Code 26 - Satisfactory Pairs

题意:给你一个正整数n,问你存在多少个正整数对a,b(a<b),满足条件:存在正整数x,y,使得ax+by=n. 就预处理出n以内所有数的约数,然后暴力枚举a,暴力枚举x,然后枚举n-ax的所有约数,判重,统计答案即可. #include<cstdio> #include<vector> #include<algorithm> using namespace std; typedef vector<int>::iterator ITER; vector

【Polya定理】【枚举约数】【欧拉函数】【Java】poj2154 Color

你随便写一下出来,发现polya原理的式子里面好多gcd是相同的,gcd(n,i)=k可以改写成gcd(n/k,i/k)=1,也就是说指数为k的项的个数为phi(n/k),就很好求了,最后除的那个n直接放到指数上即可,没必要用逆元. import java.util.*; import java.io.*; public class Main { public static int phi(int n){ int ans=n; for(int i=2;i*i<=n;++i){ if(n%i==0

【BZOJ1968】【AHoi2005】COMMON约数研究

Description Input 只有一行一个整数 N(0 < N < 1000000). Output 只有一行输出,为整数M,即f(1)到f(N)的累加和. Sample Input 3 Sample Output 5 HINT Source Day2 思路:枚举约数即可. 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 int main() 5 { 6 int n,ans=0;