UVA 1645(dp)

来源:互联网 发布:mac的QQ发文件失败 编辑:程序博客网 时间:2024/06/06 10:39

输入n,统计有多少个n节点的有根树。使得每个深度中所有节点的子节点数相同。可以根据节点的孩子个数dp。

开始写了个记忆化,dp[n][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[n][p];    if(dp[n][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]);    }}

0 0
原创粉丝点击