ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Cyclic GCDs

2019-12-17 22:01:29  阅读:320  来源: 互联网

标签:gcd Cyclic int 环上 权值 每个 dp GCDs


Cyclic GCDs

题目链接

题面描述

有\(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\)个数塞进去的方式:

  • 塞入到一个之前的环中,可以接在每个点后面,共有\(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\n",ans);
}

标签:gcd,Cyclic,int,环上,权值,每个,dp,GCDs
来源: https://www.cnblogs.com/river-flows-in-you/p/12057123.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有