2017 Multi-University Training Contest - Team 1 1006 【思维+强联通找环】
2017-07-27 11:02
417 查看
传送门
//这道题真的好, 结合了联通分量和置换群和查分约束的思想, 我还是太菜了啊, 想不到啊.
//题意就是给你一个方程, f(i)=bf(ai) , i 从给所给的序列中依次赋值, 问共有多少中方式使得这个方程成立.
第一分样例可以解释为:
110
111
001
000
思路:实际上就是从a集合到b集合的映射的组合,a中的一个循环节是一个整体,如果b中循环节的长度和a循环节的长度相同或者是因子,那么就可以置换过来,满足这个条件,将结果组合一下就好. 所以关键就是找出每一个环, 且把两个序列中的环都要找出, 并求出环的长度, 也就是找循环节和循环节法因子, 然后把结果乘起来就是了.
//找环不一定用强联通来找, 也可以暴力.
AC Code
//这道题真的好, 结合了联通分量和置换群和查分约束的思想, 我还是太菜了啊, 想不到啊.
//题意就是给你一个方程, f(i)=bf(ai) , i 从给所给的序列中依次赋值, 问共有多少中方式使得这个方程成立.
第一分样例可以解释为:
110
111
001
000
思路:实际上就是从a集合到b集合的映射的组合,a中的一个循环节是一个整体,如果b中循环节的长度和a循环节的长度相同或者是因子,那么就可以置换过来,满足这个条件,将结果组合一下就好. 所以关键就是找出每一个环, 且把两个序列中的环都要找出, 并求出环的长度, 也就是找循环节和循环节法因子, 然后把结果乘起来就是了.
//找环不一定用强联通来找, 也可以暴力.
AC Code
/** @Cain*/ const int maxn=1e5+5; int cas=1; int bel[maxn],low[maxn],dfn[maxn]; vector<int >G[maxn]; stack<int > S; int cnt ,res; int cur; int numA[maxn],numB[maxn]; int a[maxn],b[maxn]; void init(int n) { Fill(low,0); Fill(dfn,0); Fill(bel,0); for(int i=1;i<=n;i++) G[i].clear(); cnt = 1; res = 0; } void tarjan(int u) //强联通找环. { dfn[u] = low[u] = cnt++; S.push(u); for(int i=0;i<G[u].size();i++){ int v = G[u][i]; if(!dfn[v]){ tarjan(v); low[u] = min(low[u],low[v]); } else if(!bel[v]) low[u] = min(low[u],dfn[v]); } if(low[u] == dfn[u]){ res++; while(1){ int v = S.top(); S.pop(); bel[v] = res; if(u == v ) break; } } } void solve() { int n,m; while(~scanf("%d%d",&n,&m)){ Fill(numA,0); Fill(numB,0); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); a[i]++; } for(int i=1;i<=m;i++){ scanf("%d",&b[i]); b[i]++; } init(n); for(int i=1;i<=n;i++){ G[a[i]].push_back(i); } for(int i=1;i<=n;i++){ if(!dfn[i]) tarjan(i); } cur = res; for(int i=1;i<=n;i++){ numA[bel[i]]++; } //A环找完 init(m); for(int i=1;i<=m;i++){ G[b[i]].push_back(i); } for(int i=1;i<=m;i++){ if(!dfn[i]) tarjan(i); } for(int i=1;i<=m;i++){ numB[bel[i]]++; } int s[maxn] = {0}; for(int i=1;i<=m;i++){ s[numB[i]] += numB[i]; } //B环找完. ll ans[maxn] = {0}; for(int i=1;i<=cur;i++){ //循环节. for(int j=1;j<=sqrt(numA[i]);j++){ //循环节因子. if(numA[i] % j == 0){ ans[i] += s[j]; if(numA[i] / j != j) ans[i] += s[numA[i] / j]; } } } printf("Case #%d: ",cas++); ll xx = ans[1]; for(int i=2;i<=cur;i++){ xx *= ans[i]; xx %= mod; } printf("%lld\n",xx); } } int main() { int t = 1 ; //scanf("%d",&t); while(t--){ // printf("Case %d: ", cas++); solve(); //printf("\n"); } }
相关文章推荐
- 2017 Multi-University Training Contest - Team 1 1006 Function(思维 循环节)
- 2017 Multi-University Training Contest - Team 1 1006 Function(置换群)
- hdu 6045 简单的思维题 2017 Multi-University Training Contest - Team 2
- 2017 Multi-University Training Contest - Team 2 :1006 Funny Function(找规律+逆元+快速幂取模)
- 2017 Multi-University Training Contest - Team 1 1006&&HDU 6038 Function【DFS+数论】
- 2017 Multi-University Training Contest - Team 2 - 1006
- HDU-6058 Kanade's sum - 2017 Multi-University Training Contest - Team 3(思维+模拟链表)
- 2017 Multi-University Training Contest - Team 9 1005&&HDU 6165 FFF at Valentine【强联通缩点+拓扑排序】
- HDU-6140 Killer Names - 2017 Multi-University Training Contest - Team 8(思维)
- 2017 Multi-University Training Contest - Team 1 1006 Function
- 2017 Multi-University Training Contest - Team 5:1006&hdu6090、 Rikka with Graph
- 2017 Multi-University Training Contest - Team 1--1006 Function
- 2017 Multi-University Training Contest - Team 5 1006 Rikka with Graph
- 2017 Multi-University Training Contest - Team 6 1008 Kirinriki【思维题 + 尺取】
- HDU-6060 RXD and dividing - 2017 Multi-University Training Contest - Team 3(思维+最小斯坦纳树)
- HDU6069 2017 Multi-University Training Contest - Team 4 1003 Counting Divisors(唯一分解定理+思维优化)
- 2017 Multi-University Training Contest - Team 2,HDU 6045 Is Derek lying?(思维水题)
- 2017 Multi-University Training Contest - Team 1 - 1006
- 2017 Multi-University Training Contest - Team 1 B - Balala Power! (思维代码能力,贪心)
- HDU 6055 Regular polygon(计算几何+思维)——2017 Multi-University Training Contest - Team 2