题意:给出两个排列a[i]:0~n-1和b[i]:0~m-1.问有多少种F,满足F[i]=b[F[a[i]] ? n,m<=1e5.
i: 0 1 2
a[i]:1 0 2 f[0]=b[f[1]] f[1]=b[f[0]],f[2]=b[f[2]]
如果知道循环节上任意一个的f值 则循环节上剩下的f值也就确定了.
假如f[i]所在循环节长度为L,f[i]等于某个b[x].
因为:f[i]=b[f[a[i]]] =b[ b[ f[a[a[i]]] ] ]. 则b[x]经过L次变化又回到原来,则b[x]的循环节必须为L的因子.
找出a,b循环节 利用上面条件即可
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+20; const ll mod=1e9+7; int a[N],b[N],n,m,vis[N]; vector<int> c,d; int main() { int cas=0; while(cin>>n>>m) { c.clear(),d.clear(); for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<m;i++) scanf("%d",&b[i]); memset(vis,0,sizeof(vis)); for(int i=0;i<n;i++) { int cur=i,cnt=1; if(!vis[i]) { vis[i]=1; while(a[cur]!=i) { cur=a[cur]; vis[cur]=1; cnt++; } c.push_back(cnt); } } memset(vis,0,sizeof(vis)); for(int i=0;i<m;i++) { int cur=i,cnt=1; if(!vis[i]) { vis[i]=1; while(b[cur]!=i) { cur=b[cur]; vis[cur]=1; cnt++; } d.push_back(cnt); } } ll ans=1; for(int i=0;i<c.size();i++) { ll res=0; for(int j=0;j<d.size();j++) { if(c[i]%d[j]==0) res=(res+d[j])%mod; } ans=(ans*res)%mod; } printf("Case #%d: %lld\n",++cas,ans); } return 0; }
时间: 2024-10-23 17:37:58