当前位置:   article > 正文

【Atcoder】 [ABC284G] Only Once

【Atcoder】 [ABC284G] Only Once

题目链接

Atcoder方向
Luogu方向

题目解法

首先一个显然的转化是从 i i i a i a_i ai 连边,那么这样会形成一棵内向基环树,那么 S i S_i Si 即为 i i i 到环的距离
下面有一个妙妙的思路是:对于每一行来说价值和是等价的,所以不妨只计算 1 1 1 号点在所有情况下的价值和,然后将答案 × n \times n ×n 即可
考虑枚举 1 1 1 号点走到的第一个重复的点,即为 1 1 1 号点到环的距离与环的大小之和,记其为 i i i
那么 A n s = ( n − 1 ) i − 1 ‾ × n n − i × ∑ j = 1 i − 1 j = ( n − 1 ) i − 1 ‾ × n n − i × i × ( i − 1 ) 2 Ans=(n-1)^{\underline{i-1}}\times n^{n-i}\times \sum\limits_{j=1}^{i-1} j\\ =(n-1)^{\underline{i-1}}\times n^{n-i}\times \frac{i\times (i-1)}{2} Ans=(n1)i1×nni×j=1i1j=(n1)i1×nni×2i×(i1)
直接计算即可,时间复杂度 O ( n ) O(n) O(n)

#include <bits/stdc++.h>
using namespace std;
const int N=200100;
int n,P,mi[N];
inline int read(){
	int FF=0,RR=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
	for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
	return FF*RR;
}
int main(){
	n=read(),P=read();
	mi[0]=1;
	for(int i=1;i<=n;i++) mi[i]=1ll*mi[i-1]*n%P;
    int ans=0;
	for(int i=1,res=1;i<=n;res=1ll*res*(n-i)%P,i++){//枚举点1到环的距离与环大小之和
		int t=(1ll*i*(i-1)/2)%P;
		ans=(ans+1ll*res*mi[n-i]%P*t)%P;
	}
	printf("%d\n",1ll*ans*n%P);
	fprintf(stderr,"%d ms\n",int(1e3*clock()/CLOCKS_PER_SEC));
	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/52691?site
推荐阅读
相关标签
  

闽ICP备14008679号