洛谷P4161 [SCOI2009]遊戲(思維題-循環節+質數+完全揹包)

題目

windy學會了一種遊戲。

對於1到N (N<=1e3) 這N個數字,都有唯一且不同的1到N的數字與之對應。

最開始windy把數字按順序1,2,3,……,N寫一排在紙上。

然後再在這一排下面寫上它們對應的數字。

然後又在新的一排下面寫上它們對應的數字。

如此反覆,直到序列再次變爲1,2,3,……,N。

如: 1 2 3 4 5 6

對應的關係爲

1->2 2->3 3->1 4->5 5->4 6->6

windy的操作如下

1 2 3 4 5 6

2 3 1 5 4 6

3 1 2 4 5 6

1 2 3 5 4 6

2 3 1 4 5 6

3 1 2 5 4 6

1 2 3 4 5 6

這時,我們就有若干排1到N的排列,上例中有7排。

現在windy想知道,對於所有可能的對應關係,有多少種可能的排數。

思路來源

https://www.luogu.com.cn/problemnew/solution/P4161

題解

題面看似很長,實際上就是輪換麼,i每次到pi,

注意到,一個長度爲x的輪換需要x次才能轉回去,

那整體局面的循環節就是子局面循環節的最小公倍數,

問題等價於把n分成若干個整數x1,...,xm,使得m個數之和爲n,且排數=lcm(x1,...,xm)

對於每個合法的lcm,都存在一個最小的表示和sum,sum<=n,

n能表示的方案都能用其對應sum表示的方案代替,

只需要找到最小的sum,剩下的都用1補齊即可,這樣排數就可以被唯一計數了

那爲了使sum最小,一個lcm應由它所有質因子來表示,纔沒有因共同的gcd而造成的損失

故一個和值,應該對應質因子之和的方案,且爲了使2 3 5 7和2 3 7 5不被重複計算(可重集計數),

應該把相同的質因子放在一起,枚舉這種質因子填幾個,然後就變成完全揹包問題了

考慮f[i][j]+=f[i-1][j-pr[i]的k次冪,則顯然倒序滾掉這一維,

最後轉化過來之後的實現不難,然而還是比較思維一點吧

代碼

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
const int N=1e3+10;
typedef long long ll;
int n,pr[N],d[N],cnt;
ll dp[N];
int main(){
    scanf("%d",&n);
    rep(i,2,n){
        if(!d[i]){
            d[i]=i;
            pr[cnt++]=i;
        }
        for(int j=0,k;(k=pr[j]*i)<=n;++j){
            d[k]=pr[j];
            if(d[i]==pr[j])break;
        }
    }
    dp[0]=1;
    rep(i,0,cnt-1){
        per(j,n,1){
            for(int k=pr[i];k<=j;k*=pr[i]){
                dp[j]+=dp[j-k];
            }
        }
    }
    rep(i,1,n)dp[i]+=dp[i-1];
    printf("%lld\n",dp[n]);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章