HDU4658 Integer Partition(整数拆分+判断相同数)

题意:将n划分为最大值不超过n的若干个数之和,每个数最多出现m-1次。问有多少种方案?

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <cmath>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
using namespace std;
const int mod=1e9+7;
int dp[100010];
void init()
{
    memset(dp,0,sizeof(dp));
    dp[0]=1;
    for(int i=1; i<=100000; i++)
    {
        for(int j=1,r=1; i-(3*j*j-j)/2>=0; j++,r*=-1)
        {
            dp[i]+=dp[i-(3*j*j-j)/2]*r;
            dp[i]%=mod;
            dp[i]=(dp[i]+mod)%mod;
            if(i-(3*j*j+j)/2>=0)
            {
                dp[i]+=dp[i-(3*j*j+j)/2]*r;
                dp[i]%=mod;
                dp[i]=(dp[i]+mod)%mod;
            }
        }
    }
}
int solve(int n,int k)
{
    int ans=dp[n];
    for(int j=1,r=-1; n-k*(3*j*j-j)/2>=0; j++,r*=-1)
    {
        ans+=dp[n-k*(3*j*j-j)/2]*r;
        ans%=mod;
        ans=(ans+mod)%mod;
        if(n-k*(3*j*j+j)/2>=0)
        {
            ans+=dp[n-k*(3*j*j+j)/2]*r;
            ans%=mod;
            ans=(ans+mod)%mod;
        }
    }
    return ans;
}
int main()
{
    init();
    int t,n,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&k);
        printf("%d\n",solve(n,k));
    }
    return 0;
}
时间: 2024-10-06 10:32:33

HDU4658 Integer Partition(整数拆分+判断相同数)的相关文章

母函数(整数拆分、取数)

重点是对数组的初始化,把初始状态时的不取赋值为1---->nums[0][0]=1;,然后之后就能从i=1开始遍历更新nums数组(nums[j+i*k]+=nums[j];) 重点就是初始化的操作是把nums[0][0]=1; 原文地址:https://www.cnblogs.com/MekakuCityActor/p/8608573.html

判断一个整数是否是平方数

367. Valid Perfect Square 题意:不用api,判断一个整数是否是平方数. 开始的想法是直接用二分法判断是否是平方数. 错误的代码: 1 public boolean isPerfectSquare(int num) { 2 // binary search 3 int i=0; 4 int n=num; 5 while(i<=n){ 6 int mid=i+(n-i)/2; 7 int square=mid*mid; 8 if(square==num) return tr

【转载转载转载!】整数拆分问题的四种解法--尼奥普兰

整数拆分问题的四种解法 原创 2015年04月01日 21:17:09 标签: 算法 / 母函数定理 / 五边形数定理 / acm / 动态规划 整数划分问题是算法中的一个经典命题之一 所谓整数划分,是指把一个正整数n写成如下形式: n=m1+m2+m3+....+mi;(其中mi为正整数,并且1<=mi<=n),则{m1,m2,m3,....,mi}为n的一个划分. 如果{m1,m2,m3,....,mi}中的最大值不超过m,即max{m1,m2,m3,....,mi} <= m,则称

poj 2229 完全背包变形(求解整数拆分问题)

整数拆分问题:给定一个正整数n,将n拆分为若干数字的和,问有多少种方法? 此题为整数拆分问题的子问题,拆分出的数字要求是2的幂次. 定义dp[i][k]表示枚举到第k个数字时数字i的拆分方案数. 则有状态转移方程: dp[i][k] = dp[i][k - 1] + dp[i - num[k]][k]; 熟悉完全背包的朋友可以看出,这个方程和完全背包的状态转移方程如出一辙,第二维可以省去,只要将i从小到大枚举即可. 1 #include <iostream> 2 #include <cs

poj 3014 Cake Pieces and Plates 整数拆分

题意: 将m拆成n个数,允许某个数为0,求拆分方案数. 分析: 裸的整数拆分,设h(m,n)表示将m拆成n个数,允许某数为0的方案数,递推方程见代码.很有意思的是,参考上一篇写poj1221的博文中,设f(m,n)表示将m进行任意份数不允许有0的整数拆分,且最大元素小于等于m的方案数,则h(m,n)==f(m,n)....求解此等式意义... 代码: //poj 3014 //sep9 #include <iostream> using namespace std; const int max

质因数分解(给定一个整数,求该数的所有质因数)

题目:质因数分解,给定一个整数,求该数的所有质因数,例如 90 = 2*3**3*5. 首先,质数的定义(引用百度百科): 质数又称素数,有无限个.一个大于1的自然数,如果除了1和它自身外,不能被其他自然数整除(除0以外)的数称之为素数(质数):否则称为合数.根据算术基本定理,每一个比1大的整数,要么本身是一个质数,要么可以写成一系列质数的乘积:而且如果不考虑这些质数在乘积中的顺序,那么写出来的形式是唯一的. 在自然数域内,质数是不可再分的数,是组成一切自然数的基本元素. 比如,10 是由两个

整数拆分问题的四种解法【转载】

http://blog.csdn.net/u011889952/article/details/44813593 整数拆分问题的四种解法 原创 2015年04月01日 21:17:09 标签: 算法 / 母函数定理 / 五边形数定理 / acm / 动态规划 整数划分问题是算法中的一个经典命题之一 所谓整数划分,是指把一个正整数n写成如下形式: n=m1+m2+m3+....+mi;(其中mi为正整数,并且1<=mi<=n),则{m1,m2,m3,....,mi}为n的一个划分. 如果{m1,

LeetCode 343.整数拆分 - JavaScript

题目描述:给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化. 返回你可以获得的最大乘积. 题目分析 题目中"n 至少可以拆分为两个正整数的和",这个条件说明了 n 是大于 1 的整数. 对 7 来说,可以拆成 3+4,最大乘积是 12. 对 8 来说,可以拆成 3+3+2,最大乘积是 18. 解法 1: 动态规划 状态数组dp[i]表示:数字 i 拆分为至少两个正整数之和的最大乘积.为了方便计算,dp 的长度是 n + 1,值初始化为 1. 显然dp[2]等于

输入一个整数,判断其是否是2^n,是就输出这个数,不是就输出和它最接近的为2^n的那个整数。

输入一个整数,判断其是否是2^n,若是,输出这 //个数,若不是,输出和它最接近的为2^n的那个整数. 附加源代码1: #include<stdio.h> #include<stdlib.h> #include<math.h> int main() { int input;//键盘输入一个整数input int i,j;//i,j待会儿存放input与左边和右边的为2^n的差值 int m,n;//保存左边,右边的与inout最接近的2^n printf("请