您的位置:首页 > 其它

UVA 1645(dp)

2015-05-07 15:40 786 查看
输入n,统计有多少个n节点的有根树。使得每个深度中所有节点的子节点数相同。可以根据节点的孩子个数dp。

开始写了个记忆化,dp
[p]表示n个节点,第一个节点有p个孩子的方案数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000 + 5;
const ll mod = 1e9 + 7;
ll dp[maxn][maxn];
ll d(int n,int p)
{
ll & res = dp
[p];
if(dp
[p]!=-1)return res;
if(p==n-1)return res = 1;
res = 0;
n -= 1;
if(n%p)return 0;
n /= p;
for(int i = 1; i <= n-1; i++) res = (res+d(n,i))%mod;
return res;
}
int main()
{
int T;
memset(dp,-1,sizeof dp);
int cas = 0;
while(~scanf("%d",&T)&&T) {
ll res = 0;
for(int i = 1; i <= T-1; i++) {
res = (res + d(T,i))%mod;
}
res = max(res,1LL);
printf("Case %d: %lld\n", ++cas, res);
}
}

后来又改成了直接枚举孩子的res[j]表示j个时节点的答案。复杂度为n^2
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000 + 5;
const ll mod = 1e9 + 7;
ll res[maxn];
void init(int n)
{
memset(res,0,sizeof res);
res[0] = res[1] = 1;
for(int i = 1; i <= n; i++) {
int t = i - 1;
for(int j = 1; j <= i-1; j++)if(t%j==0){
res[i] = (res[i] + res[t/j])%mod;
}
}
}
int main()
{
int T;
init(1000);
int cas = 0;
while(~scanf("%d",&T)&&T) {
printf("Case %d: %lld\n", ++cas, res[T]);
}
}

最后改成了直接筛法递推的复杂度为nlogn

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000 + 5;
const ll mod = 1e9 + 7;
ll res[maxn];
void init(int n)
{
memset(res,0,sizeof res);
res[0] = res[1] = 1;
for(int i = 1; i <= n; i++) {
for(int j = i; j+1 <= n; j +=i){
res[j+1] = (res[j+1] + res[i])%mod;
}
}
}
int main()
{
int T;
init(1000);
int cas = 0;
while(~scanf("%d",&T)&&T) {
printf("Case %d: %lld\n", ++cas, res[T]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划 dp