zoukankan      html  css  js  c++  java
  • hdu 6038

    题意:给出a,b序列,求多少种f序列,f序列是f(i)=b(f(ai)).

    思路:从例子出发3  4  

            2  0  1

            0  2  3 1

       可以知道a序列有个长度为3的循环节,即a[0]=2,a[1]=0,a[2]=1, b序列有长度为1和3的循环节  长度为1的:a[0]=0;

                                                      长度为3的:a[1]=2,a[2]=3,a[3]=1;

       那么a长度3的循环节自然可以匹配长度为1的和长度为3的循环节,但如果我b改为0 2 1 3,它的循环节就变成长度为1和2的,那么就只能匹配长度为1的循环节,可以自己手动模拟下,

     1 #include<bits/stdc++.h>
     2 using namespace  std;
     3 typedef long long ll;
     4 const int N=1e5+10;
     5 const ll mod=1e9+7;
     6 
     7 int a[N],b[N];
     8 int aa[N],bb[N];
     9 int vis[N];
    10 
    11 int main(){
    12     int k=1;
    13     int n,m;
    14     while(scanf("%d%d",&n,&m)!=EOF){
    15         for(int i=0;i<n;i++) scanf("%d",&a[i]);
    16         for(int i=0;i<m;i++) scanf("%d",&b[i]);
    17         memset(vis,0,sizeof(vis));
    18         memset(aa,0,sizeof(aa));
    19         memset(bb,0,sizeof(bb));
    20         for(int i=0;i<n;i++){
    21             int cnt=0;
    22             int x=i;
    23             while(!vis[x]){
    24                 cnt++;
    25                 vis[x]=1;
    26                 x=a[x];
    27             }
    28             //cout<<cnt<<endl;
    29             aa[cnt]++;//a该循环节的个数++
    30         }
    31         memset(vis,0,sizeof(vis));
    32         for(int i=0;i<m;i++){
    33             int cnt=0;
    34             int x=i;
    35             while(!vis[x]){
    36                 cnt++;
    37                 vis[x]=1;
    38                 x=b[x];
    39             }
    40            //cout<<cnt<<endl;
    41             bb[cnt]++;//b该循环节的个数++
    42         }
    43         ll sum=1;
    44         for(int i=1;i<=n;i++){
    45             if(aa[i]){
    46                // cout<<i<<endl;
    47                 ll ans=0;
    48                 for(int j=1;j*j<=i;j++){//在b的循环节中找到和a匹配的,即a的因子
    49                     if(i%j==0){
    50                         ans=(ans+bb[j]*j)%mod;//循环节的个数*循环节的长度,代表循环节里的这些数都可以形成f
    51                        // cout<<bb[j]<<" ";
    52                         if(j*j!=i){
    53                             ans=(ans+bb[i/j]*(i/j))%mod;
    54                         }
    55                     }
    56                 }
    57               //  cout<<ans<<endl;
    58                 while(aa[i]--){//对于a每个循环节都有ans个,所以*
    59                     sum=sum*(ans)%mod;
    60                 }
    61             }
    62         }
    63         printf("Case #%d: ",k++);
    64         printf("%I64d
    ",sum);
    65     }
    66     return 0;
    67 }

     

  • 相关阅读:
    如何获取SQL Server数据库连接字符串的某些部分
    .NET同步原语Barrier简介
    模版引擎RazorEngine简介
    如何使用SQL Server实现SignalR的横向扩展
    SignalR的客户端.NET Client介绍
    一个简单的SignalR例子
    看视频学SignalR—在微软虚拟学院学习SignalR
    看视频学Bootstrap—在微软虚拟学院学习Bootstrap
    C# 窗口与控件的相关操作
    opencv——常见的操作
  • 原文地址:https://www.cnblogs.com/hhxj/p/7237973.html
Copyright © 2011-2022 走看看