有\(n\)个点,每个点有权值。
现有排列\(P\),\(p_i\)表示\(i\)个点向\(p_i\)连了一条边。
显然会形成若干个简单环。每个简单环的权值定义为环上最小的权值,一张图的权值定义为所有环的权值的乘积。
所有形成了\(k\)个简单环的图的权值和记为\(b_k\)
现在要求\(b_1,b_2...b_n\)的最大公因数。
输出对大质数取模。
\(n\le10^5\)
首先可以发现,顺序无关紧要,为了方便处理,我们把权值从小到大排序。
考虑这样的一个\(DP\)
我们设\(dp[i][j]\)表示考虑到前\(i\)个数,共形成了\(j\)个简单环的权值和。
我们考虑把第\(i+1\)个数塞进去的方式:
于是我们得到了一个\(O(n^2)\)的做法。
我们把\(dp[k]\)的生成函数写出来,设为
\[
F_k(x)=\sum_{i=0}^n dp[k][i]*x^i
\]
根据上面的转移,可知:
\[
F_{k+1}(x)=F_k(x)*(a_{k+1}x+k)
\]
于是,最终的\(dp[n]\)的生成函数为:
\[
F_n(x)=\prod_{i=0}^{n-1}(a_{i+1}x+i)
\]
可以证明,最后的\(gcd\)等于每个\(gcd\)相乘。
于是我们就愉快的做完了。
命题:\(S(x),R(x)\)为整系数多项式,每一项系数的\(gcd\)分别为\(s,r\),则多项式\(P(x)Q(x)\)每一项系数的\(gcd\)为\(sr\)
证明:不妨设\(s=r=1\),不难证明,这与原命题等价。
? 假设\(S(x)R(x)\)每一项系数的\(gcd\)为质数\(p\)的倍数,我们期望导出矛盾。
? 考虑最高次项的系数,为\(S(x)\)与\(R(x)\)的最高项系数相乘得到的结果。
? 因为最高次项系数为质数\(p\)的倍数,所以\(S(x),R(x)\)的最高项系数其中一个为\(p\)的倍数,不妨设为\(S(x)\)的最 高项系数。
? 因为系数为\(p\)的倍数,它与其他系数乘积也为\(p\)的倍数,并不影响最后多项式任何一项系数对\(p\)的整除性,所 以将\(S(x)\)的最高项次数变为\(0\),并不影响最后的\(gcd\)是否是\(p\)的倍数。
? 然后就变成了一个子问题,继续迭代,取最高次项,直到有一个多项式变为零多项式为止。
? 那么,这个零多项式,他原来的每一项系数均为\(p\)的倍数,这与假设不符,矛盾。
? 故原命题成立。
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int n;
int ans;
int a[100005];
int gcd(int a,int b){
return a%b?gcd(b,a%b):b;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
ans=a[1];
for(int i=1;i<n;i++)
ans=1ll*ans*gcd(a[i+1],i)%mod;
printf("%d\n",ans);
}
原文:https://www.cnblogs.com/river-flows-in-you/p/12057123.html