您的位置:首页 > 其它

2017 多校 Function(置换群

2017-07-26 22:17 225 查看
传送门


Function

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 1200    Accepted Submission(s): 539


Problem Description

You are given a permutation a from 0 to n−1 and
a permutation b from 0 to m−1.

Define that the domain of function f is
the set of integers from 0 to n−1,
and the range of it is the set of integers from 0 to m−1.

Please calculate the quantity of different functions f satisfying
that f(i)=bf(ai) for
each i from 0 to n−1.

Two functions are different if and only if there exists at least one integer from 0 to n−1 mapped
into different integers in these two functions.

The answer may be too large, so please output it in modulo 109+7.

 

Input

The input contains multiple test cases.

For each case:

The first line contains two numbers n, m. (1≤n≤100000,1≤m≤100000)

The second line contains n numbers,
ranged from 0 to n−1,
the i-th
number of which represents ai−1.

The third line contains m numbers,
ranged from 0 to m−1,
the i-th
number of which represents bi−1.

It is guaranteed that ∑n≤106, ∑m≤106.

 

Output

For each test case, output "Case #x: y"
in one line (without quotes), where x indicates
the case number starting from 1 and y denotes
the answer of corresponding case.

 

Sample Input

3 2
1 0 2
0 1
3 4
2 0 1
0 2 3 1

 

Sample Output

Case #1: 4
Case #2: 4

 

Source

2017 Multi-University Training Contest - Team 1

 

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  6044 6043 6042 6041 6040 

 

题目大意:

给你一个数组A,和一个数组B,数组A是【0~n-1】的排咧,数组B是【0~m-1】的排列。

现在定义F(i)=bF(ai);

问有多少种取值,使得F(i)全部合法。

写出样例2的公式:

①F(0)=bF(2)

②F(1)=bF(0)

③F(2)=bF(1)

设想一下,这个题仔细想想有映射的关系,如果定F(i)中的i一定会有对应的b 也就是说确定一个值可以确定整个值。

多往b里推几下,会发现最终会有F(i)=bbbbbbb(i) 这样递归可以得到最终的循环节 也就是一个环。

预处理A,得到A 循环节个数和 形成的循环节。同样预处理B。

如果在A循环节的基础上,B里的一定是A循环节的因子才能完成A这个循环。

对于A数组中长度为D的一个环,如果B数组中有一个环的长度为d,并且如果D%d==0.那么这个B数组的这个环的所有值,都可以作为A数组中这个环的值。那么对于A数组中的这个环来讲,答案数就多了d个。

最终的答案就是每个循环节累乘的结果

//china no.1
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;

#define pi acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=1e3+1e2;
const int maxx=1e5+1e2;
const double EPS=1e-7;
const LL MOD=1e9+7;
#define mod(x) ((x)%MOD);
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");

vector<int>G[maxx];
stack<int>S;
map<int,LL>mp;
int vis[maxx],dfn[maxx],low[maxx],bel[maxx],num[maxx],res,
a[maxx],b[maxx],num1[maxx];
int cont=1,n,m;
LL ans[maxx];
void dfs(int x)
{
dfn[x]=low[x]=cont++;
S.push(x);vis[x]=1;
int len=G[x].size();
for(int i=0; i<len; i++)
if(!vis[G[x][i]])
{
dfs(G[x][i]);
low[x]=min(low[x],low[G[x][i]]);
}
else if(vis[G[x][i]]==1)
low[x]=min(low[x],dfn[G[x][i]]);
if(dfn[x]==low[x])
{
res++;
while(1)
{
int t=S.top();
S.pop();
vis[t]=2;  //访问完成
bel[t]=res;
if(x==t)break;
}
}
}
void init()
{
me(dfn,0);me(vis,0);me(low,0);me(bel,0);me(a,0);me(b,0);
me(num1,0);mp.clear();me(num,0);me(ans,0);
res=0;cont=1;
}
void INIT()
{
me(dfn,0);me(vis,0);me(low,0);me(bel,0);me(num,0);
res=0;cont=1;
}

inline int Scan()
{
int Res=0,ch,Flag=0;
if((ch=getchar())=='-')Flag=1;
else if(ch>='0' && ch<='9')Res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')Res=Res*10+ch-'0';
return Flag ? -Res : Res;
}
int cas=1;
int main()
{
//freopen("1006.in", "r", stdin);
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]++;
G[a[i]].push_back(i);
}
for(int i=1;i<=m;i++)
{
scanf("%d",&b[i]);
b[i]++;
}
for(int i=1;i<=n;i++)
if(!vis[i]) dfs(i);
for(int i=1;i<=n;i++)
num1[bel[i]]++;
int val=res;
for(int i=1;i<=n;i++)
G[i].clear();
INIT();
for(int i=1;i<=m;i++)
G[b[i]].push_back(i);
for(int i=1;i<=m;i++)
if(!vis[i]) dfs(i);
for(int i=1;i<=m;i++)
num[bel[i]]++;
for(int i=1;i<=m;i++)
mp[num[i]]+=num[i];
for(int i=1;i<=m;i++)
G[i].clear();
for(int i=1;i<=val;i++)
for(int j=1;j<=sqrt(num1[i]);j++)
{
if(num1[i]%j==0)
{
ans[i]+=mp[j];
if(num1[i]/j!=j)
ans[i]+=mp[num1[i]/j];
}
}
LL out;
for(int i=1;i<=val;i++)
{
if(i==1) out=ans[i]%MOD;
else
{
out*=ans[i];
out%=MOD;
}
}
printf("Case #%d: %I64d\n",cas++,out);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: