HDU6038-Function 思维+组合问题
2017-07-26 14:04
393 查看
传送门
题意:
给两个数列a(元素个数为n)和b(元素个数为m),求满足f(i) = b[f(a[i])] 的组合情况有多少种
思路:
1、数列a和b各自中的每一个数都不相同,不然函数f(x)的定义域与值域就不会满足 0 ~ n-1 与 0 ~ m-1,
2、数列a中元素a0,a1,a2,a3……an-1组成的函数 x = ay 必定存在循环,且存在 1~n 个循环组成,
分析第一个样例:
a={1,0,2} b={0,1}
1->a[1]->0->1 2 ->a[2]->2
这里有两个循环 分别为 a[0]->a[1]->a[0] 和 a[2]->a[2]
同理 数列b 也是如此
3、求解:
1)要满足f(i) = b[f(a[i])],枚举每一个数列 a 中的循环 x,然后找数列
b 中的循环y的个数,需要满足 y长度 是 x长度的因子;
2)由于环可以旋转,则每一个长度为len(y)的循环y 贡献的方法 为 tol(y)= num(y) * len(y),(num(y)是长度为 len(y) 的循环的个数),将该x的每一个 tol(y) 累加求和,tol(x) = tol(y1) + tol(y2) + …… + tol(yn); yi 都会 x的因子;
3) 由于不同x之间独立,ans = tol(x1) * tol(x2) + …… + tol(xn).
题意:
给两个数列a(元素个数为n)和b(元素个数为m),求满足f(i) = b[f(a[i])] 的组合情况有多少种
思路:
1、数列a和b各自中的每一个数都不相同,不然函数f(x)的定义域与值域就不会满足 0 ~ n-1 与 0 ~ m-1,
2、数列a中元素a0,a1,a2,a3……an-1组成的函数 x = ay 必定存在循环,且存在 1~n 个循环组成,
分析第一个样例:
a={1,0,2} b={0,1}
1->a[1]->0->1 2 ->a[2]->2
这里有两个循环 分别为 a[0]->a[1]->a[0] 和 a[2]->a[2]
同理 数列b 也是如此
3、求解:
1)要满足f(i) = b[f(a[i])],枚举每一个数列 a 中的循环 x,然后找数列
b 中的循环y的个数,需要满足 y长度 是 x长度的因子;
2)由于环可以旋转,则每一个长度为len(y)的循环y 贡献的方法 为 tol(y)= num(y) * len(y),(num(y)是长度为 len(y) 的循环的个数),将该x的每一个 tol(y) 累加求和,tol(x) = tol(y1) + tol(y2) + …… + tol(yn); yi 都会 x的因子;
3) 由于不同x之间独立,ans = tol(x1) * tol(x2) + …… + tol(xn).
#include <bits/stdc++.h> using namespace std; #define LL long long #define N 100005 #define M 105 #define INF 0x3f3f3f3f #define mod 1000000007 vector<int>factor ; //factor[i] 存储 i 的因子 bool vis ; int cot_a ,cot_b ; //存储 每一个 循环x, cot_b[i] = n 表示数列 b 长度为 i 的数量为 n int a ,b ; int main() { int n,m; int cas = 1; for(int i=1;i<N;i++){ //预处理 因子 for(int j=i;j<N;j+=i){ factor[j].push_back(i); } } while(~scanf("%d%d",&n,&m)){ memset(vis,0,sizeof(vis)); int tol = 0; 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++){ if(vis[i]) continue; vis[i] = 1; int cot = 1; int w = i; while(!vis[a[w]]){ //找循环 vis[a[w]] = 1; w = a[w]; cot++; } cot_a[tol++] = cot; } memset(cot_b,0,sizeof(cot_b)); memset(vis,0,sizeof(vis)); for(int i=0;i<m;i++){ if(vis[i]) continue; vis[i] = 1; int cot = 1; int w = i; while(!vis[b[w]]){ //找循环 vis[b[w]] = 1; w = b[w]; cot++; } cot_b[cot]++; } LL ans = 1; for(int i=0;i<tol;i++){ LL w = 0; int len = factor[cot_a[i]].size(); for(int j=0;j<len;j++){ int num = factor[cot_a[i]][j]; w += cot_b[num] * num; //循环y 贡献的方法 为 tol(y)= num(y) * len(y) w %= mod; } ans = ans * w % mod; } printf("Case #%d: %lld\n",cas++,ans); } return 0; }
相关文章推荐
- hdu6038-思维-2017多校(2)-Function
- HDU6038-Function-数学+思维-2017多校Team01
- Combinations 组合 思维问题
- 递归专题-排列组合问题
- “思维问题”——“菱形”
- 第9周项目6-穷举法解决组合问题之三色球问题
- 解题笔记(21)——字符串的排列组合问题
- 2014秋C++第9周项目6参考-穷举法解决组合问题
- qt.network.ssl: QSslSocket: cannot call unresolved function 问题解决
- NWU CCCC选拔赛 1014阶乘问题(思维题)
- 排列组合问题(n取m)
- 组合问题
- 浅谈强化学习中的函数估计问题 - Function Approximation in RL
- 数的组合问题,从n个数中选出m个数,结果按照字典序排列
- 求集合的组合和排列问题
- 第九周 项目六 穷举法解决组合问题之百钱买百鸡问题
- Android自定义组合控件内子控件无法显示问题
- Rotate Function问题及解法
- HDU 6055 组合正多边形问题
- 继承与实现(组合)问题