题目传送门(内部题110)
输入格式
第一行一个整数$N$,表示小盆友的个数。
第二行$N$个整数$A_i$,如果$A_i=-1$表示$i$目前是自由身,否则$i$是$A_i$的跟班。
输出格式
一个整数$X$,表示在模$10^9+7$的情况下,期望总猜拳次数。
样例
样例输入1:
2
-1 -1
样例输出1:
1
样例输入2:
3
-1 -1 -1
样例输出2:
3
样例输入3:
4
-1 -1 -1 -1
样例输出3:
7
样例输入4:
5
-1 -1 -1 -1 -1
样例输出4:
15
样例输入5:
3
-1 -1 2
样例输出5:
2
样例输入6:
4
-1 -1 2 2
样例输出6:
4
数据范围与提示
样例$1$解释:
无论谁输谁赢,一次猜拳后,一个人就成为另外一个人的跟班,那另外一个人则胜出,游戏结束。
数据范围:
对于$10\%$的数据,满足$n=1$。
对于$50\%$的数据,满足$n\leqslant 1,000,A_i=-1$。
对于$100\%$的数据,满足$n\leqslant 100,000$。
题解
样例给这么多,而且还是第一题,一看就是给找规律的;不过为什么出题人不给个类似下面这样的样例?
4
-1 -1 1 2
其实答案就是:
$$ans=2^{(n-1)}-1-(\sum \limits_{i=1}^n2^{(sum[i]-1)}-1)$$
其中$sum[i]$表示$i$的跟班个数。
时间复杂度:$\Theta(n+\log n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h> using namespace std; const int mod=1000000007; int n; int sum[100001]; long long ans; long long qpow(long long x,long long y) { long long res=1; while(y) { if(y&1)res=res*x%mod; x=x*x%mod; y>>=1; } return res; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){int x;scanf("%d",&x);if(x!=-1)sum[x]++;} ans=qpow(2,n-1)-1; for(int i=1;i<=n;i++) ans=(ans-qpow(2,sum[i])+1+mod)%mod; printf("%lld",ans); return 0; }
rp++
原文地址:https://www.cnblogs.com/wzc521/p/11779046.html
时间: 2024-11-12 05:08:56