Cyclic GCDs

Posted river-flows-in-you

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cyclic GCDs相关的知识,希望对你有一定的参考价值。

Cyclic GCDs

题目链接

题面描述

(n)个点,每个点有权值。

现有排列(P),(p_i)表示(i)个点向(p_i)连了一条边。

显然会形成若干个简单环。每个简单环的权值定义为环上最小的权值,一张图的权值定义为所有环的权值的乘积。

所有形成了(k)个简单环的图的权值和记为(b_k)

现在要求(b_1,b_2...b_n)的最大公因数。

输出对大质数取模。

(nle10^5)

解题思路

首先可以发现,顺序无关紧要,为了方便处理,我们把权值从小到大排序。

考虑这样的一个(DP)

我们设(dp[i][j])表示考虑到前(i)个数,共形成了(j)个简单环的权值和。

我们考虑把第(i+1)个数塞进去的方式:

  • 塞入到一个之前的环中,可以接在每个点后面,共有(i)种接法。由于我们从小到大排序,所以不会改变每个环上的最小值,得到转移:(dp[i+1][j]+=i*dp[i][j])
  • 独立成环,方案数不变,多了一个(a_{i+1})的权值,得到转移:(dp[i+1][j+1]+=a_{i+1}*dp[i][j])

于是我们得到了一个(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)相乘。

于是我们就愉快的做完了。

证明

先咕着。

代码

#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
",ans);
}

以上是关于Cyclic GCDs的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客暑期多校训练营 J. Product of GCDs 不动脑子的莫比乌斯反演做法(

HDU3746 Cyclic Nacklace

codeforces E. Cyclic Components

Cyclic Nacklace HDU 3746 KMP 循环节

CodeForces 709C Letters Cyclic Shift (水题)

Codeforces Round #479 (Div. 3) E. Cyclic Components (思维,DFS)