bzoj1025

1025: [SCOI2009]游戏

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 1573  Solved: 990
[Submit][Status][Discuss]

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。

Output

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

Sample Input

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

Sample Output

【输出样例一】
3
【输出样例二】
16

HINT

【数据规模和约定】

100%的数据,满足 1 <= N <= 1000 。

Source

题意:给出一个数字n,要你将其分为几个数字,它们的和为n,如a1,a2,a3...ak,并且a1+a2+a3+,....+ak=n,问Lcd(a1,a2,a3,......,ak)有多少种

分析:公倍数可以写成(任意一个数都可以写成)x=p1^d1*p2^d2*.......*pk‘^dk‘,

那么如果Lcd(a1,a2,a3......ak) = x,那么显然p1^d1+p2^d2+......pk‘^dk‘ <= a1+a2+a3+.....+ak = n

这是显然的

那么因为只需要求最小公倍数有多少种,那么显然对于p1^d1+p2^d2+......pk‘^dk‘ = x <n 的情况,只需要将n分解成p1^d1, p2^d2, ...... , pk‘^dk‘ ,以及若干个1即可

那么问题转换成,求若干个质数的阶层相加的和小于等于n的方案数

发现,n<=1000,所以质数最多只有130个左右,这么小的数据量,而且他们的和肯定小于1000,所以背包即可

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <deque>
 6 #include <vector>
 7 #include <queue>
 8 #include <iostream>
 9 #include <algorithm>
10 #include <map>
11 #include <set>
12 #include <ctime>
13 using namespace std;
14 typedef long long LL;
15 typedef double DB;
16 #define For(i, s, t) for(int i = (s); i <= (t); i++)
17 #define Ford(i, s, t) for(int i = (s); i >= (t); i--)
18 #define Rep(i, t) for(int i = (0); i < (t); i++)
19 #define Repn(i, t) for(int i = ((t)-1); i >= (0); i--)
20 #define rep(i, x, t) for(int i = (x); i < (t); i++)
21 #define MIT (2147483647)
22 #define INF (1000000001)
23 #define MLL (1000000000000000001LL)
24 #define sz(x) ((int) (x).size())
25 #define clr(x, y) memset(x, y, sizeof(x))
26 #define puf push_front
27 #define pub push_back
28 #define pof pop_front
29 #define pob pop_back
30 #define ft first
31 #define sd second
32 #define mk make_pair
33 inline void SetIO(string Name) {
34     string Input = Name+".in",
35     Output = Name+".out";
36     freopen(Input.c_str(), "r", stdin),
37     freopen(Output.c_str(), "w", stdout);
38 }
39
40 const int N = 1010;
41 int Prime[N], Tot;
42 bool Visit[N];
43 int n;
44 LL Dp[N][N], Ans;
45
46 inline void Input() {
47     scanf("%d", &n);
48 }
49
50 inline void GetPrime() {
51     Tot = 0;
52     For(i, 2, n) {
53         if(!Visit[i]) Prime[++Tot] = i;
54         For(j, 1, Tot) {
55             if(Prime[j]*i > n) break;
56             Visit[Prime[j]*i] = 1;
57             if(!(i%Prime[j])) break;
58         }
59     }
60 }
61
62 inline void Solve() {
63     GetPrime();
64     Dp[0][0] = 1;
65     For(i, 1, Tot) {
66         For(j, 0, n) Dp[i][j] = Dp[i-1][j];
67         for(int x = Prime[i]; x <= n; x *= Prime[i])
68             For(j, 0, n-x)
69                 Dp[i][j+x] += Dp[i-1][j];
70     }
71
72     For(i, 0, n) Ans += Dp[Tot][i];
73     cout<<Ans<<endl;
74 }
75
76 int main() {
77     SetIO("1025");
78     Input();
79     Solve();
80     return 0;
81 }

时间: 2024-10-28 16:30:17

bzoj1025的相关文章

[BZOJ1025] [SCOI2009]游戏 解题报告

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

BZOJ1025: [SCOI2009]游戏

1025: [SCOI2009]游戏 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2029  Solved: 1315[Submit][Status][Discuss] Description windy学会了一种游戏.对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应.最开始windy把数字按顺序1,2,3,……,N写一排在纸上.然后再在这一排下面写上它们对应的数字.然后又在新的一排下面写上它们对应的数字.如此反复,直到序列再次变为1,

【bzoj1025】【SCOI2009】【游戏】【dp】

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

BZOJ1025 游戏

题解: 所谓对应关系,其实就是一种置换(想成一种环).对于n个数,一共有m个置换,每个置换的大小为a1,a2,.....am 转化为求a1+a2+.....am=n的最小公倍数的种类(不同的最小公倍数有多少个) 置换的大小可以为1,转化为a1+a2+.....am<=n的最小公倍数的种类 对于每个ai,可以用k个素数的乘积表示 转化为有p个不同的素数,每个素数的幂的最大值的乘积的不同数,保证全部素数的最大幂和<=n 然后dp来做就行了 参考博客 http://www.cnblogs.com/i

bzoj1025: [SCOI2009]游戏(DP)

题目大意:将长度为n的排列作为1,2,3,...,n的置换,有可能置换x次之后,序列又回到了1,2,3,...,n,求所有可能的x的个数. 看见这种一脸懵逼的题第一要务当然是简化题意...我们可以发现,序列回到原状的次数就是每个循环的规模(即在循环中的数字个数)的lcm,而且因为有n个数,显然所有循环的规模之和就是n,那么问题就被简化成了a1+a2+a3+...+ak=n,求lcm(a1,a2,a3,...,an)的个数. 现在题意已经清楚多了,那咋写呢QAQ 我们把一个数分解质因数,p为质数,

[bzoj1025][SCOI2009]游戏 (分组背包)

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

bzoj1025 [SCOI2009]游戏——因数DP

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1025 这篇博客写得真好呢:https://www.cnblogs.com/phile/p/4473192.html 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,pri[1005],cnt; long long f[1005][1005]

[BZOJ 1025] 游戏 置换群 背包DP

题意 对于一个 $n$ 阶置换群 $A$ , 它的循环节大小分别为 $a_1, a_2, ..., a_m$ , 则有 $\sum_{i = 1} ^ m a_i = n$ . 定义 $f(A)$ 为它的所有循环节的最小公倍数, 即 $f(A) = [a_1, a_2, ..., a_m]$ . 求在所有 $n$ 阶置换群中, $f(A)$ 有多少种取值. $n \le 1000$ . 分析 判断 $K$ 可不可取. $K = \prod_{i = 1} ^ r {s_r} ^ {t_r}$ 可

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734