hdu 5185 Equation(DP,思路)
2016-07-21 10:48
351 查看
Equation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 492 Accepted Submission(s): 166
Problem Description
Gorwin is very interested in equations. Nowadays she gets an equation like this
x1+x2+x3+⋯+xn=n,
and here
0≤xi≤nfor1≤i≤nxi≤xi+1≤xi+1for1≤i≤n−1
For a certain n,
Gorwin wants to know how many combinations of xi satisfies
above condition.
For the answer may be very large, you are expected output the result after it modular m.
Input
Multi test cases. The first line of the file is an integer T indicates
the number of test cases.
In the next T lines,
every line contain two integer n,m.
[Technical Specification]
1≤T<20
1≤n≤50000
1≤m≤1000000000
Output
For each case output should occupies one line, the output format is Case #id: ans, here id is the data number starting from 1, ans is the result you are expected to output.
See the samples for more details.
Sample Input
2
3 100
5 100
Sample Output
Case #1: 2
Case #2: 3
题意:从1~n里面选出n个数要求满足x1+x2+...xn=n并且xi<=x(i+1)<=xi+1,结果对m取模,问一共有几种可能序列
思路:首先分析该条件可以发现该序列一定不能从2或者2以上的数字开始
因为我们假设有n个数,然后序列从2开始,那么序列最少为2*n>n
所以序列只能从0或者1开始,并且去重后一定是连续的序列,这点应该比较容易看出来,后一个数要么是前一个数,要么是前一个数+1
那么我们把序列去重,最后的结果一定是连续序列
并且0其实对于我们的结果是没有贡献的,0只是充当了补充个数的功能,当我们0以外的数字已经达到了n的时候,我们用0来补充个数
比如n=3的时候,有一种序列 0 1 2这个时候0就是用来补充个数的
所以我们假设序列里面最后一个数是m,那么去重后的序列就是1/(0,1) 2 3...m
此时m是有个上限的,最多只能是接近sqrt(n)的一个数,我们可以用while循环求出这个数
然后我们枚举序列的最后一个数和当前序列能达到的总和,于是转换为一个DP问题
dp[i][j]表示用了0~i的数字所组成总和j的方案数(1~i的个数是没有限制的,类比完全背包=-=)
所以转移方程就是dp[i][j]=dp[i][j-i]+dp[i-1][j-i]分别表示用了0~i的数字所组成总和j-i的方案数和用了0~i-1的数字所组成总和j-i的方案数
也就是完全背包里面第一次取某个物品或者大于第一次取这个物品的两个状态了
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 50010
int dp[500]
;
int main()
{
int T,t=1;
long long n,m;
scanf("%d",&T);
while(T--)
{
scanf("%lld %lld",&n,&m);
int k=1;
while(k*(k+1)<=2*n) k++;
k--;
for(int i=0;i<=n;i++)
dp[0][i]=0;
for(int i=1;i<=k;i++)
dp[i][0]=0;
dp[0][0]=1;
for(int i=1;i<=k;i++)
{
for(int j=i;j<=n;j++)
{
dp[i][j]=(dp[i][j-i]+dp[i-1][j-i])%m;
}
}
long long ans=0;
for(int i=1;i<=k;i++)
ans=(ans+dp[i]
)%m;
printf("Case #%d: %lld\n",t++,ans);
}
return 0;
}
相关文章推荐
- a 与 &a 的区别
- LeetCode之求组合数之和二CombinationSumII
- iOS—最全的真机测试教程
- 在iOS中使用字体文件.ttf(icon font,可缩放矢量图)
- 全国地区的省份、城市、区县 最新Sql脚本
- pat 1099. Build A Binary Search Tree (30)
- 通过编写插件个性化你的IntelliJ IDEA
- java中静态代码块的用法 static用法详解
- eclipse 设置默认编码为Utf-8
- php 获取服务器IP
- ubuntu14.04+openni2.2.0.33+primesense carmine1.09
- Spinner And NumberPicker 使用详解
- linux终端自定义命令的别名
- 使用file_get_contents提交http post
- 字符串函数的使用
- hdu-1072 Nightmare(DFS+剪枝)
- Eclipse打开WorkSpace已存在工程
- 使用ActionBar缺少主题时jar包中抛类型转换异常
- c++学习笔记(二):数据类型
- java提高篇(十二)-----代码块