码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-07-25 22:43:08      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:highlight   dfs   pre   ++z   nts   efi   bool   lca   int   

把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;
}

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

标签:highlight   dfs   pre   ++z   nts   efi   bool   lca   int   

原文地址:http://www.cnblogs.com/autsky-jadek/p/7236671.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!