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
[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]);
}
}
相关文章推荐
- uva 1645 Count dp
- UVA 1645 Count——dp
- UVALive 4857 Halloween Costumes(区间DP)
- uva 11795洛克人的难题(集合dp)
- Coupons - UVa 10288 概率dp
- UVA 11825 状态压缩DP
- UVA 11552 Fewest Flops(DP)
- UVA 10271 Chopsticks(线性DP)
- UVA 437 The Tower of Babylon (dp + DAG最长序列)
- UVA 1025 DP
- 【区间dp】【记忆化搜索】UVALive - 3516 - Exploring Pyramids
- dp uva1218
- 【UVA 11584】【简单dp】Partitioning by Palindromes【给定一个字符串, 问最少分为几部分可使各部分均为回文串】
- Compromise - POJ 2250 UVa 531 dp
- UVA 10817 Headmaster's Headache 状压DP
- UVA 10271 Chopsticks(dp)
- UVA-10163 Storage Keepers DP
- UVALive 3490 Generator(AC自动机+dp+高斯消元)
- UVA11456--dp,LIS
- Jin Ge Jin Qu hao - UVa 12563 dp背包