【HDU6038】Function(循环节+计数)

来源:互联网 发布:事情正在起变化 知乎 编辑:程序博客网 时间:2024/04/27 22:23

记录一个菜逼的成长。。

2017 Multi-University Training Contest - Team 1

题目链接

题目大意:

给你长度为n的的a序列和长度为mb序列。
求有多少种函数满足fi=bfai

笔记(官方题解

考虑置换a的循环节,长度为l,那么有fi=bfai=bbfaai=bbfil times b

那么fi的值在置换b中所在的循环节的长度必须为l的因数。

而如果fi值确定下来了,这个循环节的另外l1个数的函数值也都确定下来了。

答案就是ki=1j|lijcalj.其中k是置换a中循环节的个数,li表示置换a中第i个循环节的长度,calj表示置换b中长度为j的循环节的个数。

#include <bits/stdc++.h>using namespace std;#define rep(i,l,r) for( int i = l; i <= r; i++ )#define rep0(i,l,r) for( int i = l; i < r; i++ )#define ALL(v) (v).begin(),(v).end()#define cl(a,b) memset(a,b,sizeof(a))#define clr clear()#define pb push_back#define mp make_pair#define fi first#define se secondtypedef long long LL;typedef pair<int,int> PII;const int INF = 0x3f3f3f3f;const int MOD = 1e9 + 7;const int maxn = 100000 + 10;int a[maxn],b[maxn],vis[maxn];int cnt[maxn],fa[maxn];int main(){  int cas = 1,n,m;  while(~scanf("%d%d",&n,&m)){    rep(i,1,n)scanf("%d",a+i),a[i]++;    rep(i,1,m)scanf("%d",b+i),b[i]++;    cl(vis,0);    int len = 0;    //计算a的循环节    rep(i,1,n){      int l = 0,ind = a[i];      while(!vis[a[ind]]){        vis[a[ind]] = 1;        l++;ind = a[ind];      }      if(l)fa[len++] = l;    }    cl(vis,0);cl(cnt,0);    //统计b的循环节的长度数量    rep(i,1,m){      int l = 0,ind = b[i];      while(!vis[b[ind]]){        vis[b[ind]] = 1;        l++;ind = b[ind];      }      if(l)cnt[l]++;    }    LL ans = 1;    rep0(i,0,len){      int num = fa[i];      LL sum = 0;      int k = sqrt(num + 0.5);      for( int j = 1; j <= k; j++ ){        if(num % j == 0){          sum += j * cnt[j];          sum %= MOD;          if(num/j != j){            sum += num/j * cnt[num/j];            sum %= MOD;          }        }      }      ans = ans * sum % MOD;    }    printf("Case #%d: %lld\n",cas++,ans);  }  return 0;}
原创粉丝点击