洛谷 CF1043F Make It One 解题报告
CF1043F Make It One
題意
從一堆數(shù)中選擇最少的數(shù),使它們的\(\gcd=1\)
輸入輸出格式
輸入格式
第一行:一個(gè)正整數(shù)\(n\)。
第二行:\(n\)個(gè)正整數(shù),給出了這個(gè)數(shù)列。
輸出格式
一行,\(-1\)(如果任意選擇都不能得到\(1\)分)或一個(gè)正整數(shù)(表示選擇的數(shù)的數(shù)量的最小值)
數(shù)據(jù)范圍
\(1\leq n\leq 300,000 , 1\leq a_i \leq 300,000\).
第二次遇到此類題了,反演理解的不好,不清楚怎么用反演理解這個(gè)題。
不過容斥的方法還挺神的(雖然可能感覺有點(diǎn)套路?
發(fā)現(xiàn)選擇的數(shù)不會超過\(7\)個(gè),因?yàn)?span id="ze8trgl8bvbq" class="math inline">\(2 \times 3 \times 5 \times 7 \times 11 \times 13 \times 17 >3\times 10^5\)
直接暴力枚舉選幾個(gè)數(shù)
然后設(shè)\(dp_{i,j}\)表示選\(i\)了\(i\)個(gè)數(shù)且這\(i\)個(gè)數(shù)\(\gcd=j\)的方案數(shù)
\(dp_{i,j}=\binom{cnt_j}{i}-\sum_{j|k}f_{i,k}\)
\(cnt_j\)表示有多少個(gè)數(shù)是\(j\)的倍數(shù)
Code:
#include <cstdio> #include <cstring> #define ll long long const int N=3e5+10; const ll mod=1e9+7; ll qp(ll d,ll k) {ll f=1;while(k){if(k&1) f=f*d%mod;d=d*d%mod;k>>=1;}return f; } ll fac[N],inv[N],dp[N]; int n,cnt[N],mx; int main() {scanf("%d",&n);fac[0]=1;for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;inv[n]=qp(fac[n],mod-2);for(int i=n-1;~i;i--) inv[i]=inv[i+1]*(i+1)%mod;for(int a,i=1;i<=n;i++) scanf("%d",&a),++cnt[a],mx=mx>a?mx:a;for(int i=1;i<=mx;i++)for(int j=i<<1;j<=mx;j+=i)cnt[i]+=cnt[j];for(int i=1;i<=7;i++){memset(dp,0,sizeof(dp));for(int j=mx;j;j--){dp[j]=cnt[j]>=i?fac[cnt[j]]*inv[cnt[j]-i]%mod*inv[i]%mod:0;if(dp[j])for(int k=j<<1;k<=mx;k+=j)(dp[j]-=dp[k])%=mod;(dp[j]+=mod)%=mod;}if(dp[1]) return printf("%d\n",i),0;}puts("-1");return 0; }2018.11.5
轉(zhuǎn)載于:https://www.cnblogs.com/butterflydew/p/9911563.html
總結(jié)
以上是生活随笔為你收集整理的洛谷 CF1043F Make It One 解题报告的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pandas 如何判断指定列是否(全部)
- 下一篇: JAVA国际化输出日期格式