2017 多校训练 1006 Function

  

Function

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 273    Accepted Submission(s): 99

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

/*
* @Author: Lyucheng
* @Date:   2017-07-25 15:25:56
* @Last Modified by:   Lyucheng
* @Last Modified time: 2017-07-25 20:42:28
*/
/*
 题意:给你两个序列,定义一种函数 f(i)=b[f(ai)] ,问你已给出的序列可以构造出的函数的数量

 思路:实际上就是从a集合到b集合的映射的组合,a中的一个循环节是一个整体,如果b中循环节的长度和a循环节的长度相同
    或者是因子,那么就可以置换过来,满足这个条件,将结果组合一下就好

 感悟:好气啊,想出来,但是没想到因子这个条件...
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>

#define MAXN 100005
const long long MOD = 1e9+7;
#define LL long long
using namespace std;

int n,m;
int a[MAXN];
int b[MAXN];
bool visa[MAXN];
bool visb[MAXN];
vector<int> va;
vector<int> vb;
int ca=1;

void init(){
    va.clear();
    vb.clear();
    memset(visa,false,sizeof visa);
    memset(visb,false,sizeof visb);
    memset(a,0,sizeof a);
    memset(b,0,sizeof b);
}

int main(){
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    while(scanf("%d%d",&n,&m)!=EOF){

        init();
        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<n;i++){//求A的循环节
            if(visa[i]==true) continue;

            int cur=0;
            int x=a[i];
            while(x!=a[x]){
                if(visa[x]==true) break;//走到了标记过的点 可能遇到没返回自己的循环了,也可能返回自己了
                visa[x]=true;
                cur++;
                x=a[x];
            }
            if(x==a[i]){
                if(cur==0)
                    va.push_back(1);
                else
                    va.push_back(cur);
            }else{
                va.push_back(1);
                int cnt=0;
                while(x!=a[x]){
                    cnt++;
                    if(cnt>=cur) break;
                    visa[x]=false;
                    x=a[x];
                }
                visa[a[i]]=true;
            }
        }

        for(int i=0;i<m;i++){//求B的循环节
            if(visb[i]==true) continue;

            int cur=0;
            int x=b[i];
            while(x!=b[x]){
                if(visb[x]==true) break;//走到了标记过的点 可能遇到没返回自己的循环了,也可能返回自己了
                visb[x]=true;
                cur++;
                x=b[x];
            }
            if(x==b[i]){
                if(cur==0)
                    vb.push_back(1);
                else
                    vb.push_back(cur);
            }else{
                vb.push_back(1);
                int cnt=0;
                while(x!=b[x]){
                    cnt++;
                    if(cnt>=cur) break;
                    visb[x]=false;
                    x=b[x];
                }
                visb[b[i]]=true;
            }
        }

        LL res=1;
        for(int i=0;i<va.size();i++){
            LL cur=0;
            for(int j=0;j<vb.size();j++){
                if(va[i]%vb[j]==0){
                    cur+=( (LL)(vb[j]) ) %MOD;
                    cur%=MOD;
                }
            }
            res=( (res%MOD) * (cur%MOD) )%MOD;
        }

        printf("Case #%d: %d\n",ca++,res);
    }
    return 0;
}
时间: 2024-08-19 04:38:41

2017 多校训练 1006 Function的相关文章

【链表】2017多校训练3 HDU 6058 Kanade&#39;s sum

acm.hdu.edu.cn/showproblem.php?pid=6058 [题意] 给定一个排列,计算 [思路] 计算排列A中每个数的贡献,即对于每个ai,计算有ni个区间满足ai是区间中的第k大,那么ai对答案的贡献就是ai*ni 以ai为起点,统计ai右边离ai最近的,比ai大的k个数的位置 同理统计左边的位置,组合得到答案 关键是得到比ai大的离ai最近的k个数的位置 因为是排列,所以每个数都不相等,可以记录每个数的位置,然后从小到大枚举ai,这样维护一个双向链表,保证链表中的数就是

【2017多校训练08 1002】【HDOJ 6134】Battlestation Operational

典型的数列反演题. 运用莫比乌斯反演的一个结论 $[n = 1] = \sum_{d | n} \mu(d)$,将表达式做如下转化: $$ ans = \sum_{i=1}^n \sum_{j=1}^i (\lfloor \frac{i-1}{j} \rfloor + 1) \sum_{d | i \land d | j} \mu(d) \\ = \sum_{d=1}^n \mu(d) \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor} \sum_{j=1}^i (

【极角排序+双指针线性扫】2017多校训练七 HDU 6127 Hard challenge

acm.hdu.edu.cn/showproblem.php?pid=6127 [题意] 给定平面直角坐标系中的n个点,这n个点每个点都有一个点权 这n个点两两可以连乘一条线段,定义每条线段的权值为线段两端点点权的乘积 现在要过原点作一条直线,要求这条直线不经过任意一个给定的点 在所有n个点两两连成的线段中,计算与这条直线有交点的线段的权值和 最大化这个权值和并输出 题目保证,给定的n个点不重合且任意两个点的连线不经过原点 [思路] 一条经过原点的直线把n个点分成两个半平面A,B 假设A中的点权

【2017多校训练2+计算几何+板】HDU 6055 Regular polygon

http://acm.hdu.edu.cn/showproblem.php?pid=6055 [题意] 给定n个格点,问有多少个正多边形 [思路] 因为是格点,只可能是正方形 枚举正方形的对角线,因为有两条对角线,最后答案要/2 也可以枚举正方形的边,因为有四条边,答案要/4 看当前对角线确定的正方形是否存在,用几何知识求出目标点的坐标,然后二分查找目标点是否存在 [Accepted] 1 #include <cstdio> 2 #include <cstring> 3 #incl

【双向bfs】2017多校训练十 HDU 6171 Admiral

[题意] 现在给出一个三角矩阵,如果0编号的在点(x,y)的话,可以和(x+1,y),(x-1,y),(x+1,y+1),(x-1,y-1)这些点进行交换. 我们每一次只能对0点和其他点进行交换.问最少步数,使得最终变成: 0 1 1 2 2 2 3 3 3 3 4 4 4 4 4 5 5 5 5 5 5 [思路] [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef un

【组合数+Lucas定理】2017多校训练七 HDU 6129 Just do it

http://acm.hdu.edu.cn/showproblem.php?pid=6129 [题意] 对于一个长度为n的序列a,我们可以计算b[i]=a1^a2^......^ai,这样得到序列b 重复这样的操作m次,每次都是从上次求出的序列a得到一个新序列b 给定初始的序列,求重复m次操作后得到的序列 [思路] 假定n=5,我们模拟一次可以发现,经过m次操作后a1在b1......bn中出现的次数为: m=0: 1 0 0 0 0 m=2: 1 2 3 4 5 m=3: 1 3 6 10 1

2017 多校训练题解1 [A.Add More Zero] 数学

题目链接: 题目大意:给出m,求(2^m)-1化成十进制是几位 关键思想:当m很大时,-1可以不考虑.2^m=10^x=(10^log2(10))^x,x就等于2^m除以一个系数. 代码如下: #include <iostream> #include <cstdio> #include <cmath> using namespace std; double x=3.321928095;//精度一定要够,否则WA int main(){ int cnt=0; int n;

hdu 4902 Nice boat(2014多校训练第4场 1006)

Nice boat                                                                           Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description There is an old country and the king fell in love with a d

2016暑假多校训练参赛感想

参赛感想 这是第一次参加暑假多校训练,应该也会是人生中最后一次,我真的很庆幸能参加这个训练,和全国几乎所有高校的ACMer一起在一个平台上做题!昨天为止多校已经完全结束,今天看到叉姐的训练感想(叉姐的感想链接),我觉得我也有必要写下自己的训练感想. 人的眼界总是狭窄的,当在自己的学校站在前几名的时候觉得自己还不错,应该会有不错的将来,但是当第一次参加国赛(2015 南阳站)的时候我便被别人实力所震撼,我突然觉得自己在别人的眼里简直就是小学生,菜到不行.别人在5个小时可以AK,而我连最水的题也要想