您的位置:首页 > 其它

POJ 2229 Sumsets(递推,找规律)

2015-10-17 11:52 281 查看
构造,递推,因为划分是合并的逆过程,考虑怎么合并。

先把N展开成全部为N个1
然后合并,因为和顺序无关,所以只和出现次数有关
情况有点多并且为了避免重复,分类,C[i]表示序列中最大的数为2^i时的方案数

树形表示合并 (UVA 10562 Undraw the Trees的表示方法。。。
7 (2^0) (7表示2^0出现的次数)
_ _ _
| | |
1 2 3 (2^1) (7个1可以合并成1~3个2)

_ _
| |
1 1 (2^2) (继续合并)
这棵树是分形的,子树的形态由根结点的值决定。

f
表示方案
当n是偶数,第一层会增加一颗子树 其值为 n/2, f
= f[n-1]+f[n/2]

当n是奇数,树的形态不变 ,f
= f[n-1]

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;

const int mod = 1e9, maxn = 1e6+1;
int dp[maxn];

//#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
int n; cin>>n;
dp[1] = 1;
for(int i = 2; i <= n ; i++) {
dp[i] = dp[i-1] + (i&1?0:dp[i>>1]);
if(dp[i]>=mod) dp[i] -= mod;
}
cout<<dp
<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: