dp小总结

写在前面

Just some easy problem solving with dynamic programming.

(Given me a dynamic programming table, I can tell you a new world.)

juruo眼中的神仙dp,(测试博客园的blog最多允许多长系列)

lv1 codeforces 724D

日常口胡:傻子也知道,答案最多sqrt(n)个,切了.

正常思路:性质1:答案最多sqrt(n)个:1.1<=k<=sqrt(n)  不同答案最多sqrt(n)个 2.k>sqrt(n) ans<=n/k<=sqrt(n) 最多sqrt(n)个.

    性质2:满足单调性(不难从k的方案中构造出答案相同的k-1的方案), 

于是二分/整体二分边界,O(nsqrt(n)logn)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define N 1005
 5 #define M 15
 6 int n,d,mod,dp[N][M][N],inv[N];
 7 int pw(int a,int b){int r=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)r=1ll*r*a%mod;return r;}
 8 int main()
 9 {
10     scanf("%d%d%d",&n,&d,&mod);
11     if(n<=2){puts("1");return 0;}
12     for(int i=1;i<n;i++)inv[i]=pw(i,mod-2);
13     dp[1][0][0]=dp[1][d-1][0]=1;
14     for(int i=2;i<=n;i++)for(int j=1;j<=d;j++)for(int k=1;k<i;k++)
15     {
16         dp[i][j][k]=dp[i][j][k-1];
17         int r=dp[k][d-1][k-1],c=1;
18         for(int t=1;t*k<i&&t<=j;t++,r++)
19         {
20             c=1ll*c*r%mod*inv[t]%mod;
21             dp[i][j][k]=(dp[i][j][k]+1ll*dp[i-t*k][j-t][min(i-t*k-1,k-1)]*c)%mod;
22         }
23     }
24     int ans=dp[n][d][(n+1)/2-1];
25     if(n%2==0)ans=(ans+1ll*dp[n/2][d-1][n/2-1]*(dp[n/2][d-1][n/2-1]+1)/2)%mod;
26     printf("%d
",ans);
27     return 0;
28 }
View Code
原文地址:https://www.cnblogs.com/xyleo/p/10283075.html