题意:
给你a数组和b数组, 问你f 函数的种类。 使得a[i] = b[f[a[i]]]?
思路:
因为a 数组 和b 数组 都是0~n-1的排列。
所以一定有一个循环节:
比如 2 1 0 3的话 ,就有两个循环节。
2 1 0 和 3
那么要想使得是一个循环的a 赋值,就也得找b 的循环节。
假如我们得到了b的循环节。
那么对于每一个a 来说, 只要b 是a 的因子, 那么b就可以给a 赋值。方案数是b 循环节的长度。
那么把所有的乘起来即可。
无力吐槽:
因为初始化数组 是循环跑的, 忘记了n 和m 不一定相等, wa了一天。。。。。。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int maxn = 100000 + 10;
int a[maxn];
int b[maxn];
int sum[maxn];
int vis[maxn];
vector<int>va, vb;
void dfs(int cur,int c[],int n,int ans,int flag){
vis[cur] = 1;
if (vis[c[cur] ]) {
if (flag) {
sum[ans]++;
}
else va.push_back(ans);
}
else {
dfs(c[cur], c, n, ans+1, flag);
}
}
const int mod = 1e9 + 7;
void add(long long& ans, long long x){
ans += x;
if (ans >= mod) ans -= mod;
}
int main(){
int n,m;
int ks = 0;
while(~scanf("%d %d",&n, &m)){
va.clear();
for (int i = 0; i < n; ++i){
scanf("%d", a+i);
}
memset(sum,0,sizeof sum); /// 醉了= =
for (int i = 0; i < m; ++i){
scanf("%d",&b[i]);
}
memset(vis,0,sizeof vis);
for (int i = 0; i < n; ++i){
if (!vis[i]){
dfs(i,a, n, 1, 0);
}
}
memset(vis,0,sizeof vis);
for (int i = 0; i < m; ++i){
if (!vis[i]){
dfs(i,b, m, 1, 1);
}
}
long long ans = 1LL;
for (int i = 0; i < va.size(); ++i){
int x = va[i];
int mm = sqrt(x + 0.5);
long long tmp = 0LL;
for (int j = 1; j <= mm; ++j){
if (x % j == 0){
if (j * j != x){
if (sum[j])add(tmp, (long long)j * (long long)sum[j]);
if (sum[x/j])add(tmp, (long long)(x/j) * (long long)sum[x/j] );
}
else {
if (sum[j])add(tmp, (long long)j * (long long)sum[j]);
}
}
}
ans = (ans * tmp) % mod;
}
printf("Case #%d: %I64d\n", ++ks,ans);
}
return 0;
}
/**
3 2
1 0 2
0 1
3 4
2 0 1
0 2 3 1
Case #1: 4
Case #2: 4
**/
FunctionTime Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Problem Description a from 0 to n−1 and a permutation b from 0 to m−1.
Input The input contains multiple test cases.
Output Case #x: y" in one line (without quotes), where x indicates the case number starting from 1 and y
Sample Input
Sample Output
Source 2017 Multi-University Training Contest - Team 1
Recommend liuyiding | We have carefully selected several similar problems for you: 6055 6054 6053 6052 6051
Statistic | Submit | Discuss | Note |
FunctionTime Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Problem Description a from 0 to n−1 and a permutation b from 0 to m−1.
Input The input contains multiple test cases.
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
Sample Input 3 21 0 20 13 42 0 10 2 3 1
Sample Output Case #1: 4Case #2: 4
Source 2017 Multi-University Training Contest - Team 1
Recommend liuyiding | We have carefully selected several similar problems for you: 6055 6054 6053 6052 6051
Statistic | Submit | Discuss | Note |