17暑假多校联赛1.6 HDU 6038 Function

Function

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

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


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6038

分析

题意:给定一个关系式 f(i)=b[f(a[i])] 和数组a,b,计算满足这个关系式不同的可能性数目
可以转化为求环的问题,有多少种方式可以构成题目要求的环,即b的环可以有多少种方式画成a的环
样例一:

i: 0,1,2
a: 1,0,2
b: 0,1

根据关系式 f(i)=b[f(a[i])] 可得

///a环
f(0)=b[f(a[0])]=b[f(1)]
f(1)=b[f(a[1])]=b[f(0)]

f(2)=b[f(a[2])]=b[f(2)]
///易看出a[0]和a[1]组成一个环,a[2]单独成环

///b环
如果f(0)=b[0]
因为f(0)=b[f(1)],则f(1)=0=b[0]
因为f(1)=b[f(0)],则f(0)=0=b[0]

如果f(0)=b[1]
因为f(0)=b[f(1)],则f(1)=1=b[1]
因为f(1)=b[f(0)],则f(0)=1=b[1]
///易看出b[0]单独成环,b[1]单独成环

这里写图片描述
由图易知,a的两个环都可以由b的两个环构成,则由b构成a总共有2+2=4种方式。
样例二:

i: 0,1,2,3
a: 2,0,1
b: 0,2,3,1

根据关系式 f(i)=b[f(a[i])] 可得

///a环
f(0)=b[f(a[0])]=b[f(2)]
f(1)=b[f(a[1])]=b[f(0)]
f(2)=b[f(a[2])]=b[f(1)]
///易看出a[0],a[1],a[2]组成一个环

///b环
如果f(0)=b[0]
因为f(0)=b[f(2)],则f(2)=0=b[0]
因为f(2)=b[f(1)],则f(1)=0=b[0]
因为f(1)=b[f(0)],则f(0)=0=b[0]

如果f(0)=b[1]
因为f(0)=b[f(2)],则f(2)=1=b[3]
因为f(2)=b[f(1)],则f(1)=3=b[2]
因为f(1)=b[f(0)],则f(0)=2=b[1]
///易看出b[0]单独成环,b[1],b[2],b[3]组成一个环

这里写图片描述
由图易知,a的一个环可以由b的两个环构成,但b的第二个环与a环可以有三种不同的对应关系,则由b构成a总共有1+3=4种方式。

所以也就是b环长度应为a环长度的因数才能满足与a环的对应关系,只要这个思路明白了,代码很好理解,记得不断对1e9+7取余

代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int MOD=1e9+7;
const int maxn=100100;
int n,m,cal[2][maxn],a[maxn],b[maxn],ans=1;
///cal[0][i]表示b环中长度为i的环出现的次数
///cal[1][i]表示a环中长度为i的环出现的次数
bool vis[maxn];
///vis[i]表示位置i是否出现过,出现过则说明成环
void dfs(int t, int l, int *a, int k)
{
    if(vis[t])
    {
        cal[k][l]++;
        return;
    }
    vis[t] = 1;
    dfs(a[t],l+1,a,k);
}
int main()
{
    int ca = 0;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0; i<n; i++)
            scanf("%d",a+i);
        for(int i=0; i<m; i++)
            scanf("%d",b+i);
        memset(cal,0,sizeof(cal));
        memset(vis,0,sizeof(vis));
        for(int i=0; i<m; i++)
            if(!vis[i])dfs(i,0,b,0);
        memset(vis,0,sizeof(vis));
        for(int i=0; i<n; i++)
            if(!vis[i])dfs(i,0,a,1);
        ans=1;
        for(int i=1; i<=n; i++)
            if(cal[1][i])
            {
                int lim=(int)sqrt(i+0.5),ta = 0;
                for(int j=1; j<=lim; j++)
                    if(i%j==0)
                    {
                        (ta+=(ll)cal[0][j]%MOD*j%MOD)%=MOD;
                        if(j*j!=i)ta+=((ll)cal[0][i/j]%MOD*(i/j)%MOD)%MOD;
                    }
                for(int j=1; j<=cal[1][i]; j++)
                    ans=(ll)ans*ta%MOD;
            }
        printf("Case #%d: %d\n",++ca,ans);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值