2017 Multi-University Training Contest
来源:互联网 发布:我的恐怖妻子 知乎 编辑:程序博客网 时间:2024/06/03 14:55
传送门
//这道题真的好, 结合了联通分量和置换群和查分约束的思想, 我还是太菜了啊, 想不到啊.
//题意就是给你一个方程, 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"); }}
阅读全文
0 0
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- #2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- #2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- String类——常见字符串操作指令
- android ndk error :undefined reference to.
- QtableView选择范围操作 通过MAP存储选择行 获取最上行号和最下行号 上移下移一行等一系列操作
- 链表--已知集合A和B的元素分别用不含头结点的单链表存储,函数difference()用于求解集合A与B的差集,并将结果保存在集合A的单链表中。
- BZOJ 1086 [SCOI2005]王室联邦
- 2017 Multi-University Training Contest
- 使用redis进行缓存
- Lua 闭包知识点 -- 学习过程笔记,会比较乱
- Vuejs几个小实例
- 责任链模式--Chain of Responsibility Pattern
- 扩展欧几里得算法
- DeprecationWarning: `open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instea
- 【Unity技巧】调整画质(贴图)质量
- poj3579 Median (二分-查找第K大的值)