码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1025[SCOI2009]游戏 - 背包dp

时间:2018-02-14 16:42:12      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:getchar   一个   close   oid   ons   问题   stream   std   read   

1025: [SCOI2009]游戏

Time Limit: 1 Sec  Memory Limit: 162 MB

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 
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想知道,对于所有可能的对应关系,有多少种可
能的排数。

Input

  包含一个整数N,1 <= N <= 1000

Output

  包含一个整数,可能的排数。

Sample Input

【输入样例一】
3
【输入样例二】
10

Sample Output

【输出样例一】
3
【输出样例二】
16
 
 
很容易发现,每一种对应关系都可以看成几个环,这些环的长度和就是一个N的划分
现在的问题就转化成对于所有N的划分,不同的lcm共有多少种
 
于是进一步转化,因为lcm只由质数的最高次幂决定
而对于任意一个$p1^ {a1} + p2 ^ {a2} + p3 ^ {a3} + ...pi ^ {ai} <= N$
都是一组解
这样我们就可以用 f[i][j] 表示 第i个质数 和为 j 来计算答案了
 
 
技术分享图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #define LL long long
 6 
 7 using namespace std;
 8 
 9 const int MAXN = 1e3 + 10;
10 int N;
11 int cnt = 0;
12 LL f[MAXN][MAXN];
13 int flag[MAXN];
14 int prime[MAXN];
15 void init()
16 {
17     for(int i = 2; i <= N; i++) {
18         if(!flag[i]) {
19             prime[++cnt] =i;
20         }
21         for(int j = 1; j <= cnt && prime[j] * i <= N; j++) {
22             flag[prime[j] * i] = 1;
23             if(i % prime[j] == 0) {
24                 break;
25             }
26         }
27     }
28 }
29 inline LL read()
30 {
31     LL x = 0, w = 1; char ch = 0;
32     while(ch < 0 || ch > 9) {
33         if(ch == -) {
34             w = -1;
35         }
36         ch = getchar();
37     }
38     while(ch >= 0 && ch <= 9) {
39         x = x * 10 + ch - 0;
40         ch = getchar();
41     }
42     return x * w;
43 }
44 
45 int main()
46 {
47     N = read();
48     init();
49     f[0][0] = 1;
50     for(int i = 1; i <= cnt; i++) {
51         for(int j = N; j >= 0; j--) {
52             f[i][j] = f[i - 1][j];
53             for(int k = prime[i]; k <= j; k = prime[i] * k) {
54                 f[i][j] += f[i - 1][j - k];
55             }
56         }
57     }
58     LL ans = 0;
59     for(int j = 0; j <= N; j++) {
60         ans += f[cnt][j];
61     }
62     printf("%lld\n", ans);
63     return 0;
64 }
View Code

 

bzoj 1025[SCOI2009]游戏 - 背包dp

标签:getchar   一个   close   oid   ons   问题   stream   std   read   

原文地址:https://www.cnblogs.com/wuenze/p/8448465.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!