P4161-[SCOI2009]游戏【dp】
生活随笔
收集整理的這篇文章主要介紹了
P4161-[SCOI2009]游戏【dp】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P4161
題目大意
一個1~n1\sim n1~n的排列,f(x)f(x)f(x)表示在置換xxx下置換多少次才能回到原來的排列,求在所有置換下f(x)f(x)f(x)的所有可能的值的數量。
解題思路
一個置換的fff值就是這個置換的所有循環大小的lcmlcmlcm,問題轉換為將nnn分成若干個數的和,求這些數的lcmlcmlcm可能的數量。
拆成的一個循環對于lcmlcmlcm的貢獻我們也可以拆分質因數的形式,所以我們直接讓拆分成的數一定是質數是不會影響答案的。
考慮dpdpdp,設fi,jf_{i,j}fi,j?表示已經考慮了前iii個質數,這些數的和為jjj時的答案,那么有fi,j=∑fi,j?prijkf_{i,j}=\sum_{}f_{i,j-pri_j^k}fi,j?=∑?fi,j?prijk??
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=1100; ll n,f[N][N],pri[N],cnt; bool v[N]; int main() {scanf("%lld",&n);for(ll i=2;i<=n;i++){if(!v[i])pri[++cnt]=i;for(ll j=1;j<=cnt&&i*pri[j]<=n;j++){v[i*pri[j]]=1;if(i%pri[j]==0)break;}}f[0][0]=1;for(ll i=1;i<=cnt;i++)for(ll j=0;j<=n;j++){f[i][j]=f[i-1][j];if(pri[i]>j)continue;for(ll k=pri[i];k<=j;k*=pri[i])f[i][j]+=f[i-1][j-k];}ll ans=0;for(ll i=0;i<=n;i++)ans+=f[cnt][i];printf("%lld",ans); return 0; }總結
以上是生活随笔為你收集整理的P4161-[SCOI2009]游戏【dp】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 死而后已的已是什么意思
- 下一篇: 1953年属相 在1953出生的属相