zoukankan      html  css  js  c++  java
  • NOIP2001提高组复赛B 数的划分

    题目链接:https://ac.nowcoder.com/acm/contest/249/B

    题目大意:

      略

    分析1(记忆化搜索):

      方法为减而治之,把n划分成k份的答案就相当于每次把n分成a,b两个数,再把a分成k-1份,然后把每次a分成k-1份的答案相加即可。注意点是每轮分出来的b要不大于上一轮分出来的b。

    代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3  
     4 #define rep(i,n) for (int i = 0; i < (n); ++i)
     5 #define For(i,s,t) for (int i = (s); i <= (t); ++i)
     6 #define rFor(i,t,s) for (int i = (t); i >= (s); --i)
     7 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
     8 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)
     9  
    10 #define pr(x) cout << #x << " = " << x << "  "
    11 #define prln(x) cout << #x << " = " << x << endl
    12  
    13 #define ALL(x) x.begin(),x.end()
    14 #define INS(x) inserter(x,x.begin())
    15  
    16 #define ms0(a) memset(a,0,sizeof(a))
    17 #define msI(a) memset(a,inf,sizeof(a))
    18  
    19 #define pii pair<int,int> 
    20 #define piii pair<pair<int,int>,int> 
    21 #define mp make_pair
    22 #define pb push_back
    23 #define fi first
    24 #define se second
    25  
    26 inline int gc(){
    27     static const int BUF = 1e7;
    28     static char buf[BUF], *bg = buf + BUF, *ed = bg;
    29      
    30     if(bg == ed) fread(bg = buf, 1, BUF, stdin);
    31     return *bg++;
    32 } 
    33  
    34 inline int ri(){
    35     int x = 0, f = 1, c = gc();
    36     for(; c<48||c>57; f = c=='-'?-1:f, c=gc());
    37     for(; c>47&&c<58; x = x*10 + c - 48, c=gc());
    38     return x*f;
    39 }
    40  
    41 typedef long long LL;
    42 const int maxN = 1e5 + 7;
    43  
    44 int n, k; 
    45 // f[i][j][k]表示数i分成j分的分法总数,k为限制条件,每种分法每份的值不能超过k,用来排除重复
    46 // f[i][j][k] = f[i-1][j-1][1] + f[i-2][j-1][2] + ……+ f[i-min(k, i-1)][j-1][min(k, i-1)]
    47 int f[201][7][202];
    48  
    49 int solve(int x, int y, int z){
    50     int ret = 0;
    51     if(x < y) return 0;
    52     if(y == 1) return x <= z ? 1 : 0;
    53     if(f[x][y][z]) return f[x][y][z];
    54      
    55     For(i, 1, x-1) {
    56         if(x-i > z) continue;
    57         ret += solve(i, y-1, x-i);
    58     }
    59     f[x][y][z] = ret;
    60     return ret;
    61 }
    62  
    63 int main(){
    64     scanf("%d%d", &n, &k);
    65     printf("%d
    ", solve(n, k, 201));
    66     return 0;
    67 }
    View Code

    分析2(DP):

      见代码内注释

    代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3  
     4 #define rep(i,n) for (int i = 0; i < (n); ++i)
     5 #define For(i,s,t) for (int i = (s); i <= (t); ++i)
     6 #define rFor(i,t,s) for (int i = (t); i >= (s); --i)
     7 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
     8 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)
     9  
    10 #define pr(x) cout << #x << " = " << x << "  "
    11 #define prln(x) cout << #x << " = " << x << endl
    12  
    13 #define ALL(x) x.begin(),x.end()
    14 #define INS(x) inserter(x,x.begin())
    15  
    16 #define ms0(a) memset(a,0,sizeof(a))
    17 #define msI(a) memset(a,inf,sizeof(a))
    18  
    19 #define pii pair<int,int> 
    20 #define piii pair<pair<int,int>,int> 
    21 #define mp make_pair
    22 #define pb push_back
    23 #define fi first
    24 #define se second
    25  
    26 inline int gc(){
    27     static const int BUF = 1e7;
    28     static char buf[BUF], *bg = buf + BUF, *ed = bg;
    29      
    30     if(bg == ed) fread(bg = buf, 1, BUF, stdin);
    31     return *bg++;
    32 } 
    33  
    34 inline int ri(){
    35     int x = 0, f = 1, c = gc();
    36     for(; c<48||c>57; f = c=='-'?-1:f, c=gc());
    37     for(; c>47&&c<58; x = x*10 + c - 48, c=gc());
    38     return x*f;
    39 }
    40  
    41 typedef long long LL;
    42 const int maxN = 1e5 + 7;
    43  
    44 int n, k; 
    45 // f[i][j]表示数i分成j份的分法总数
    46 /*
    47     当i < j时,很明显没法分,所以f[i][j] = 0;
    48     当i == j时,只有一种分法,所以f[i][j] = 1;
    49     当i > j时,考虑从小到大分,第1个如果分1,那么f[i][j] = f[i-1][j-1];
    50   第1个如果分大于1的数,可以对所有j份都减一,然后再分,即 f[i][j] = f[i-j][j]; 
    51   根据加法原则,f[i][j] = f[i-1][j-1] + f[i-j][j];
    52 */
    53 int f[201][7]; 
    54  
    55 int main(){
    56     scanf("%d%d", &n, &k);
    57     For(i, 1, n) f[i][1] = 1; // 无论什么数,分成一份都只有一种 
    58     For(i, 2, k)
    59         For(j, 2, n)
    60             if(j >= i) f[j][i] = f[j-1][i-1] + f[j-i][i];
    61       
    62     printf("%d
    ", f[n][k]);
    63     return 0;
    64 }
    65  
    View Code
  • 相关阅读:
    线程的等待与唤醒
    多线程start()与run()的区别
    Thread与Runnable
    关于i++和++i的一些见解
    Mysql优化(转)
    Java 注解
    Java 泛型(转)
    Java 中的CAS
    CAS ABA问题
    Java 线程池分析
  • 原文地址:https://www.cnblogs.com/zaq19970105/p/10753087.html
Copyright © 2011-2022 走看看