hdu 6050 Function 想法题

Function

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

题目链接

题意:给你一个a数组和b数组,叫你构造f函数满足所有的f(i)=bf(ai)

解题思路:对于a数组中的一个长度为l的环,我们只需要找在b中长度为 l的约数的环使得a数组中的数与b数组中的数一一对应就好,例如a={1,2,3,0},b={1,0},则我们可以让a0->b1,a1->b0,a2->b1,a3->b0或者a0->b0,a1->b1,a2->b0,a3->b1,则这样就是两种情况,然后我们能得知,对于两个对应的a,b环,f的种类其实就为b环的长度,因此我们便可以直接得出ans=(b中与a环对应的环的长度的总和相乘)

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll n,m,a[100005],b[100005],mark[100005];
ll len;
ll s2[100005];
ll ans;
const ll mod=1000000007;
vector<ll>p[100005];
vector<ll>q;
void init(){
    for(ll i=1;i<=100000;i++){
        for(ll j=1;j*j<=i;j++){
            if(i%j==0&&j*j!=i){
                p[i].push_back(j);
                p[i].push_back(i/j);
            }
            else if(i%j==0&&j*j==i)    p[i].push_back(j);
        }
    }
}
int main(){
    init();
    ll cas=1;
    while(scanf("%lld%lld",&n,&m)!=EOF){
        q.clear();
        ans=1;
        memset(s2,0,sizeof(s2));
        for(ll i=0;i<n;i++)    scanf("%lld",&a[i]);
        for(ll i=0;i<m;i++)    scanf("%lld",&b[i]);
        memset(mark,0,sizeof(mark));
        for(ll i=0;i<n;i++){
            if(mark[i]==0){
                mark[i]=1;
                len=1;
                ll now=a[i];
                while(mark[now]==0){
                    mark[now]=++len;
                    now=a[now];
                }
                q.push_back(len);
            }
        }
        memset(mark,0,sizeof(mark));
        for(ll i=0;i<m;i++){
            if(mark[i]==0){
                mark[i]=1;
                len=1;
                ll now=b[i];
                while(mark[now]==0){
                    mark[now]=++len;
                    now=b[now];
                }
                s2[len]++;
            }
        }
        for(ll i=0;i<q.size();i++){
            ll sum=0;
            for(ll j=0;j<p[q[i]].size();j++){
                sum=(sum+s2[p[q[i]][j]]*p[q[i]][j])%mod;
            }
            ans=(ans*sum)%mod;
        }
        printf("Case #%lld: %lld\n",cas++,ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值