bzoj1025 [SCOI2009]遊戲
阿新 • • 發佈:2017-06-02
inline getc sta 大小 long long 寫上 pre eve 一個
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想知道,對於所有可能的對應關系,有多少種可能的排數。
3
【輸入樣例二】
10
3
【輸出樣例二】
16
Description
windy學會了一種遊戲。對於1到N這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
2 3 1 4 5 6
3 1 2 5 4 6
1 2 3 4 5 6
這時,我們就有若幹排1到N的排列,上例中有7排。現在windy想知道,對於所有可能的對應關系,有多少種可能的排數。
Input
包含一個整數N,1 <= N <= 1000
Output
包含一個整數,可能的排數。
Sample Input
【輸入樣例一】3
【輸入樣例二】
10
Sample Output
【輸出樣例一】3
【輸出樣例二】
16
正解:置換+背包。
這題要求對於一個數列的任意一種置換,有多少種循環節。
很顯然,答案就是把$n$個數的置換進行循環分解,每個循環大小的$lcm$。
那麽就是說對於$n$,我們需要把它分成若幹數的和,求出這些數的$lcm$的方案數。
這裏不加證明地給出一個結論,答案就是使得$p1^{a1}+p2^{a2}+...+pn^{an}<=n$的方案數,其中$p$為質數,很顯然這個結論是對的。
那麽我們篩出$[1,n]$的所有質數,做一遍背包就行了,具體實現看代碼吧。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4#include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 19 20 using namespace std; 21 22 int prime[1010],vis[1010],n,cnt; 23 ll f[1010][1010],ans; 24 25 il int gi(){ 26 RG int x=0,q=1; RG char ch=getchar(); 27 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 28 if (ch==‘-‘) q=-1,ch=getchar(); 29 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 30 return q*x; 31 } 32 33 il void sieve(){ 34 for (RG int i=2;i<=n;++i){ 35 if (!vis[i]) prime[++cnt]=i; 36 for (RG int j=1,k;j<=cnt;++j){ 37 k=i*prime[j]; if (k>n) continue; 38 vis[k]=1; if (!i%prime[j]) break; 39 } 40 } 41 return; 42 } 43 44 il void work(){ 45 n=gi(),sieve(),f[0][0]=1; 46 for (RG int i=1;i<=cnt;++i){ 47 for (RG int j=0;j<=n;++j) f[i][j]=f[i-1][j]; 48 for (RG int j=prime[i];j<=n;j*=prime[i]) 49 for (RG int k=0;k+j<=n;++k) f[i][k+j]+=f[i-1][k]; 50 } 51 for (RG int i=0;i<=n;++i) ans+=f[cnt][i]; 52 printf("%lld\n",ans); return; 53 } 54 55 int main(){ 56 File("game"); 57 work(); 58 return 0; 59 }
bzoj1025 [SCOI2009]遊戲