链接  http://acm.hdu.edu.cn/showproblem.php?pid=6038

题意: 
给你一个a序列,代表0到n-1的排列;一个b序列代表0到m-1的排列。问你可以找出多少种函数关系f,f的定义域内的i都满足f(i)=b[f(a[i])]; 
分析:这个主要是找循环节 循环节导致函数有多种情况 找到每段循环节的 取值 种数 相乘起来就是答案
比如说:如果 a 序列是 2 0 1 那么我们可以发现

f[0] = b[f(a[0])]     f[0]  = b[f(2)] 
f[1] = b[f(a[1])]     f[1]  = b[f(0)] 
f[2] = b[f(a[2])]     f[2]  = b[f(1)]

对于这组数来说,假如我们先指定了f(0)对应的在b中的值,那么根据第2个式子,就可以得出f(1),根据f(1)就又可以得出f(2),最后根据f(2)就可以检验f(0)的值是否正确。

仔细观察左边的柿子 (定义域)i与a[ i ] 是循环的 如果想使上述成立,必须右边的柿子(值域)i与b[ i ] 也存在其约数长度的循环节。

如果不是约数长度的循环节会使上述假设矛盾    自己写一下就知道了 只有被整出才会成立。

每个定义域的循环节都可以与每个值域的循环节匹配(满足红字匹配成功)

那么就是找两个序列的不相交的循环节,对于定义域里面的每一个循环节都找出来有多少种情况。每一个循环节的情况数为它所能匹配的值域循环节的长度 和。每个循环节的情况数乘起来就是答案了

样例一  (1+1)*(1+1)=4; a两个环(长度 2 1)           b两个个环(长度 1 1)       2与1 1匹配   1与1 1 匹配

样例二  (1+3)=4;           a一个环(长度 3)                b两个环(长度 1 3)         3与1 3匹配

注   对于一个a循环节  若b循环节中没有能与之匹配的   答案为零   想想为什么  不用特判累积过程中可以处理掉

AC代码

 #include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
using namespace std;
const int maxn= 1e5+;
const int mod= 1e9+;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int n,m;
int a[maxn],b[maxn];
int vis[maxn],loop_a[maxn],loop_b[maxn]; //loop存循环节长度
int main()
{
int kase=;
while(scanf("%d %d",&n,&m)!=EOF)
{
for(int i=; i<n; i++)
scanf("%d",&a[i]);
for(int i=; i<m; i++)
scanf("%d",&b[i]);
memset(vis, , sizeof(vis));      //标记是否访问过 找不相交的循环节
memset(loop_b, , sizeof(loop_b));
memset(loop_a, , sizeof(loop_a));
int cnt1=,cnt2=; //cnt记录循环节个数
for(int i = ; i < n; i++)
{
if(!vis[i]) //过程自己模拟一下就明了了
{
int x = a[i];
int len = ;
while(!vis[x])
{
len++;
vis[x] = ;
x = a[x];
}
if(len!=)
loop_a[cnt1++]=len; //保存循环节
}
}
memset(vis, , sizeof vis);
for(int i = ; i < m; i++) //b同理
{
if(!vis[i])
{
int x = b[i];
int len = ;
while(!vis[x])
{
len++;
vis[x] = ;
x = b[x];
}
if(len!=)
loop_b[cnt2++]=len;
}
}
ll ans=;
for(int i=; i<cnt1; i++) //枚举a与b的循环节 试了不会超时 还有更快一些的做法
{
ll sum=;                //记录每个循环节的情况数
for(int j=; j<cnt2; j++)
{
if(loop_a[i]%loop_b[j]==)    //只有是约数才能匹配
{
sum=(sum+loop_b[j])%mod; //加进去 取模
}
}
ans=(ans*sum)%mod; //乘到答案里面
}
printf("Case #%d: %lld\n",++kase,ans);
}
return ;
}

作者水平有限 欢迎大佬纠错!

多校真jb难啊~~~~~QAQ

太菜了

2017多校第一套&&hdu6038 思维 数学的更多相关文章

  1. HDU 6041 I Curse Myself(点双联通加集合合并求前K大) 2017多校第一场

    题意: 给出一个仙人掌图,然后求他的前K小生成树. 思路: 先给出官方题解 由于图是一个仙人掌,所以显然对于图上的每一个环都需要从环上取出一条边删掉.所以问题就变为有 M 个集合,每个集合里面都有一堆 ...

  2. HDU-6035 Colorful Tree(树形DP) 2017多校第一场

    题意:给出一棵树,树上的每个节点都有一个颜色,定义一种值为两点之间路径中不同颜色的个数,然后一棵树有n*(n-1)/2条 路径,求所有的路径的值加起来是多少. 思路:比赛的时候感觉是树形DP,但是脑袋 ...

  3. hdu 6044 : Limited Permutation (2017 多校第一场 1012) 【输入挂 组合数学】

    题目链接 参考博客: http://blog.csdn.net/jinglinxiao/article/details/76165353 http://blog.csdn.net/qq_3175920 ...

  4. hdu 6035:Colorful Tree (2017 多校第一场 1003) 【树形dp】

    题目链接 单独考虑每一种颜色,答案就是对于每种颜色至少经过一次这种的路径条数之和.反过来思考只需要求有多少条路径没有经过这种颜色即可. 具体实现过程比较复杂,很神奇的一个树形dp,下面给出一个含较详细 ...

  5. 2017 多校5 hdu 6093 Rikka with Number

    2017 多校5 Rikka with Number(数学 + 数位dp) 题意: 统计\([L,R]\)内 有多少数字 满足在某个\(d(d>=2)\)进制下是\(d\)的全排列的 \(1 & ...

  6. hdu6074[并查集+LCA+思维] 2017多校4

    看了标答感觉思路清晰了许多,用并查集来维护全联通块的点数和边权和. 用另一个up[]数组(也是并查集)来保证每条边不会被重复附权值,这样我们只要将询问按权值从小到大排序,一定能的到最小的边权和与联通块 ...

  7. hdu6038[找规律+循环节] 2017多校1

    /*hdu6038[找规律+循环节] 2017多校1*/ #include<bits/stdc++.h> using namespace std; typedef long long LL ...

  8. hdu6035[dfs+思维] 2017多校1

    /*hdu6035[dfs+思维] 2017多校1*/ //合并色块, 妙啊妙啊 #include<bits/stdc++.h> using namespace std; ; const ...

  9. 2019年牛客多校第一场B题Integration 数学

    2019年牛客多校第一场B题 Integration 题意 给出一个公式,求值 思路 明显的化简公式题,公式是分母连乘形式,这个时候要想到拆分,那如何拆分母呢,自然是裂项,此时有很多项裂项,我们不妨从 ...

随机推荐

  1. 动态WebApi

    动态WebApi实现了直接对Service的调用,其实没有跨过ApiController,只是我们自己创建出ApiController 实现主要分以下几步 一 对默认WebApi服务的替换 ApiGl ...

  2. 快速学习Bash

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁转载. Shell是Linux下经典的文本互动方式,而Bash是现在最常用的一种Shell.我在这里总结了Bash ...

  3. scala写算法-用小根堆解决topK

    topK问题是指从大量数据中获取最大(或最小)的k个数,比如从全校学生中寻找成绩最高的500名学生等等. 本问题可采用小根堆解决.思路是先把源数据中的前k个数放入堆中,然后构建堆,使其保持堆序(可以简 ...

  4. js文件加载优化

    在js引擎部分,我们可以了解到,当渲染引擎解析到script标签时,会将控制权给JS引擎,如果script加载的是外部资源,则需要等待下载完后才能执行. 所以,在这里,我们可以对其进行很多优化工作. ...

  5. lesson - 2 笔记 yum /single /rescue /

    一. yum  作用:                     yum 命令是在Fedora 和RedHat 以及SUSE 中基于rpm 的软件包管理器,它可以使系统管理人员交互和自动化地更新与管理R ...

  6. 多线程-Timer重入

    多线程Timer重入问题 由于使用多线程定时器,就会出现如果一个Timer处理没有完成,到了时间下一个照样会发生,这就会导致重入. 对付重入问题通常的办法是加锁,但是对于 Timer却不能简单的这样做 ...

  7. UWP 手绘视频创作工具技术分享系列 - 有 AI 的手绘视频

    AI(Artificial Intelligence)正在不断的改变着各个行业的形态和人们的生活方式,图像识别.语音识别.自然语言理解等 AI 技术正在自动驾驶.智能机器人.人脸识别.智能助理等领域中 ...

  8. VMware虚拟机下为Ubuntu添加磁盘

    20G的磁盘还是不够用啊,正好复习下磁盘分区和逻辑卷. 关闭虚拟机,打开VMware,右键虚拟机点击设置,点下下方的添加,就可以添加磁盘了. 进入虚拟机,查看: root@ubuntu:/# fdis ...

  9. Wechat 微信端调用“微信支付接口”的正确方式

    微信端的项目中,比如微信商城之类的,肯定会涉及到微信支付这一块: 下面直接上详细的代码: var data = {--}; // 调用微信支付需要的数据 function onBridgeReady( ...

  10. Send Email in .NET Core 2.0

    在.NET Core 1.0 中,SMTP Client代码并没有被移植,直到.NET Core 2.0的发布.使用下面的代码: static void Main(string[] args) { S ...