zoukankan      html  css  js  c++  java
  • 51Nod-1259-整数划分 V2

    51Nod-1259-整数划分 V2

    将N分为若干个整数的和,有多少种不同的划分方式,例如:n = 4,{4} {1,3} {2,2} {1,1,2} {1,1,1,1},共5种。由于数据较大,输出Mod 10^9 + 7的结果即可。

    Input

    输入1个数N(1 <= N <= 50000)。

    Output

    输出划分的数量Mod 10^9 + 7。

    Input示例

    4

    Output示例

    5

    题解

    分块DP
    复杂度O(n*sqrt(n))

    设m = sqrt(n)

    我们可以先考虑使用1~m凑成数的方案, 完全背包即可

    对于剩下的m+1 ~ n 我们发现每个数最多使用 m 次
    然后
    g[i][j] 表示使用了i个数(m+1~m+i)和为j的方案数
    令m++
    g[i][j] = g[i-1][j-m] + g[i][j-i]
    这什么意思呢?
    对于一个序列,我们有两种操作:
    1.添加一个基数m
    2.给每个数+1(注意这里的j是正着枚举的,所以可重复给每个数加一)

    Code

    #include<bits/stdc++.h>
    #define LL long long
    #define RG register
    using namespace std;
    
    inline int gi() {
        int f = 1, s = 0;
        char c = getchar();
        while (c != '-' && (c < '0' || c > '9')) c = getchar();
        if (c == '-') f = -1, c = getchar();
        while (c >= '0' && c <= '9') s = s*10+c-'0', c = getchar();
        return f == 1 ? s : -s;
    }
    const int N = 50010, Mod = 1e9+7;
    int f[N], g[250][N], s[N];
    int main() {
        //freopen(".in", "r", stdin);
        //freopen(".out", "w", stdout);
    	int n = gi(), m = sqrt(n)+1;
    	f[0] = 1;
    	for (int i = 1; i < m; i++)
    		for (int j = i; j <= n; j++)
    			(f[j] += f[j-i]) %= Mod;
    	int ans = 0;
    	g[0][0] = 1;
    	s[0] = 1;
    	for (int i = 1; i < m; i++) {
    		for (int j = m; j <= n; j++) {
    			g[i][j] = (g[i-1][j-m] + g[i][j-i]) % Mod;
    			s[j] = (s[j] + g[i][j]) % Mod;
    		}
    	}
    	for (int i = 0; i <= n; i++)
    		ans = (ans + (LL)f[i]*s[n-i]%Mod) % Mod;
    	printf("%lld
    ", ans);
        return 0;
    }
    
    
  • 相关阅读:
    RBAC-基于角色的访问控制
    django缓存机制
    drf JWT认证
    drf自动生成接口文档
    drf多表断表操作
    drf过滤排序分页异常处理
    drf认证权限频率
    drf路由组件
    drf视图组件
    drf请求与响应
  • 原文地址:https://www.cnblogs.com/zzy2005/p/9890404.html
Copyright © 2011-2022 走看看