1. 程式人生 > >NOIp模擬3 遊戲

NOIp模擬3 遊戲

for 新的 += 問題 說明 std 示例 col 輸出格式

試題描述

  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
  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想知道,對於所有可能的對應關系,有多少種可能的排數。

輸入格式

一個整數N

輸出格式

一個整數,可能的排數。

輸入示例

輸入樣例一:
3

輸入樣例二:
10

輸出示例

輸出樣例一:
3

輸出樣例二:
16

註釋說明

30%的數據,滿足 1 <= N <= 10
100%的數據,滿足 1 <= N <= 1000

【分析】

對於原序列,每個數都有唯一且不同的數與之對應,這很像函數關系。

而對於對應序列,每個數的原像的是唯一的,所以序列中必定有若幹個首尾相接的環,所有環中的數的總和為n。

又因為一個長度為m的環經過k*m次變換可以回到原來的狀態,所以這個問題轉化成了求若幹個和為n的數的最小公倍數有多少種。

再因為若幹個數的LCM是這若幹個數中出現過的質因數中最高冪的乘積,而質數冪都是不同的,所以這個問題最後轉化成了完全背包問題...

註意這裏不足n的話可以用1補齊,任何數乘1都還是原數,這裏也相當於背包可以不裝滿。

【代碼】

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n, len=1;
 5 long long ans;
 6 long long a[1020], dp[1020];
 7 int pr[200]={0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41
, 43, 47, 53, 59, 61, 67, 71, 73, 8 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 9 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 10 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 11 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 12 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 13 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 14 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 15 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 16 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 17 991, 997};//偷懶打了個質數表 18 19 int main() { 20 cin >> n; 21 dp[0]=1; 22 for (int i=1;i<=168;++i) 23 for (int j=n;j>=pr[i];--j) 24 for (int k=pr[i];k<=j;k*=pr[i]) 25 dp[j]+=dp[j-k]; 26 for (int i=0;i<=n;++i) 27 ans+=dp[i]; 28 cout << ans << endl; 29 }

NOIp模擬3 遊戲