The Bovine Shuffle

T h e   B o v i n e   S h u f f l e The\ Bovine\ Shuffle The Bovine Shuffle

题目链接: l u o g u   P 4089 luogu\ P4089 luogu P4089 / j o z j   6661 jozj\ 6661 jozj 6661

题目

F J FJ FJ 坚信快乐的牛可以产出更多的牛奶,因此 F J FJ FJ 在牛棚里安装了一个巨大的迪斯科球并且打算让奶牛们学会跳舞。
F J FJ FJ在许多出名的奶牛舞中选择了一种叫做 B o v i n e   S h u f f l e Bovine\ Shuffle Bovine Shuffle 的舞蹈。这种舞蹈由 F J FJ FJ N N N 头奶牛组成。 N N N头奶牛以一种顺序排成一行,接着表演数次 s h u f f l e shuffle shuffle。每次的 s h u f f l e shuffle shuffle 会将奶牛重新排列。 F J FJ FJ 为了让奶牛们更加快乐,让奶牛们更容易找到重新排列后的位置,他标记了 N N N 头奶牛的位置。在最开始,所有奶牛排成一排,第一头奶牛会在位置 1 1 1 上,第二只在 2 2 2 上,以此类推。
我们用 N N N 个正整数 a 1 a_1 a1, a 2 a_2 a2, . . . ... ..., a n a_n an来描述每次的 s h u f f l e shuffle shuffle a i ai ai说明了在位置 i i i上的奶牛在经过这回合的 s h u f f l e shuffle shuffle 之后,会跑到位置 a i a_i ai上。令 F J FJ FJ 倍感非洲的是,即使 i i i j j j 不同, a i ai ai也可能会等于 a j aj aj!所以可能在一次 s h u f f l e shuffle shuffle 后,有多头奶牛会跑到同一位置上,在这之后这群奶牛也会一同行动。
作为一名资深的养牛大户&坑牛专家的 F J FJ FJ 猛然发现,无论经过多少次的 s h u f f l e shuffle shuffle,一直都有 k k k 个位置上有奶牛。 F J FJ FJ现在要你在 1 1 1 秒内帮他得出 k k k 的值,否则就赏你 1 0 18   m o d   10 10^{18}\ mod\ 10 1018 mod 10 大板!

输入

第一行包含一个整数, N N N
第二行包含 N N N个整数,描述题目中的 a 1 a_1 a1 ​ , a 2 a_2 a2 ​ , … … , a n a_n an

输出

一个整数,代表 k k k

样例输入

4
3 2 1 3

样例输出

3

思路

这道题其实要求出所有环的长度之和。
至于为什么,我们把牛的移动方向看做连箭头,那么就变成了一个有向图。
那么一个环里面的牛就会不停的交换位置,不会重叠。但是如果有某个点指向了环的某一个地方,这个点的牛就会和环里面的牛重叠。
所以我们只要找出不在环里面的点,然后统计出所有环的长度之和就可以了。

代码

#include<cstdio>
#include<cstring>

using namespace std;

int n, a, to[1000001], ru[1000001], ans;
bool in[1000001], in2[1000001];

void dfs(int now) {
	in[now] = 1;
	ru[to[now]]--;
	if (!ru[to[now]]) dfs(to[now]);
}

int dfs1(int now) {
	if (in2[now]) return 0;
	in2[now] = 1;
	return 1 + dfs1(to[now]);
}

int main() {
//	freopen("shuffle.in", "r", stdin);
//	freopen("shuffle.out", "w", stdout);
	
	scanf("%d", &n);//读入
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a);//读入
		to[i] = a;//连边
		ru[a]++;//记录入读数
	}
	
	for (int i = 1; i <= n; i++)
		if (!ru[i] && !in[i]) dfs(i);//找出不在环内的点
	for (int i = 1; i <= n; i++)
		if (!in2[i] && !in[i]) ans += dfs1(i);//统计在环中的点的数量
	
	printf("%d", ans);//输出
	
//	fclose(stdin);
//	fclose(stdout);
	
	return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值