母函数当中经典的问题 正是整数拆分问题
所谓整数拆分即把整数分解成若干整数的和(相当于把n个无区别的球放到n个无标志的盒子,盒子允许空,也允许放多于一个球)。
整数拆分成若干整数的和,办法不一,不同拆分法的总数叫做拆分数。
hdu 1028 裸的整数拆分问题
直接来个模版
#include
#include
#include
#include
#include
#include
#include
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 100100
#define INF 0x7fffffff
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
int a[130],b[130];
//g(x)=(1+x+x^2+x^3+……)(1+x^2+x^4+x^6+……)(1+x^3+x^6+……).....
int main()
{
//freopen("ceshi.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<=n;i++)
{
a[i]=1;
b[i]=0;//首先对a初始化,由第一个表达式(1+x+x2+..xn)初始化,把质量从0到n的所有值都初始化为1.
}
for(int i=2;i<=n;i++)// i从2到n遍历,这里i就是指第i个表达式
{
for(int j=0;j<=n;j++)
for(int k=0;k+j<=n;k+=i)//k是指第 i个表达式中参数的指数 每次加i
{
b[j+k]+=a[j];
}
for(int j=0;j<=n;j++)
{
a[j]=b[j];
b[j]=0;//给b重新赋值为0 b记录的是每个表达式中的值
}
}
printf("%d\n",a[n]);
}
return 0;
}
hdu 1398
把连续的整数值 替换成连续整数的平方
所以在k的循环中 变化的值需要修改 增加的是一个数的平方
#include
#include
#include
#include
#include
#include
#include
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 100100
#define INF 0x7fffffff
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
int a[310],b[310];
int main()
{
freopen("ceshi.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
for(int i=0;i<=n;i++)
{
a[i]=1;
b[i]=0;
}
for(int i=2;i<=n;i++)
{
for(int j=0;j<=n;j++)
for(int k=0;k+j<=n;k+=i*i)
{
// cout<<"jjj "<
hdu 1085
给出 1元 2元 5元硬币的个数 求出这些硬币不能组合得到的数的最小值
还是记录有那些数可以通过这些硬币组合得到 最后找出不能组合得到的最小值
最小到大枚举这些硬币的组合 枚举过程中要注意 范围的变化
#include
#include
#include
#include
#include
#include
#include
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 100100
#define INF 0x7fffffff
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
int a[8010],b[8010];
int main()
{
//freopen("ceshi.txt","r",stdin);
int n1,n2,n3;
while(scanf("%d%d%d",&n1,&n2,&n3)!=EOF)
{
if(n1==0&&n2==0&&n3==0)
break;
MEM(a,0);
MEM(b,0);
for(int i=0;i<=n1;i++)
a[i]=1;
for(int i=0;i<=n1;i++)
for(int j=0;j<=n2*2;j+=2)//注意范围的变化
b[i+j]+=a[i];
for(int i=0;i<=n1+n2*2;i++)
{
a[i]=b[i];
b[i]=0;
}
for(int i=0;i<=n1+n2*2;i++)
for(int j=0;j<=n3*5;j+=5)
b[i+j]+=a[i];
for(int i=0;i<=n1+n2*2+n3*5;i++)
{
a[i]=b[i];
b[i]=0;
}
int x;
for(x=0;x<=n1+n2*2+n3*5;x++)
{
if(a[x]==0)
{
printf("%d\n",x);
break;
}
}
if(x==(n1+n2*2+n3*5+1))
printf("%d\n",x);
}
return 0;
}
hdu 1171
给出一些不同的值和这些值的个数 然后需要将这些值进行划分 分成两部分
尽量使得两部分的值相等
首先枚举这些值能够组成的所有的值的情况 然后 将和分成两部分 一直向下找 看哪个值是能够被组成的
#include
#include
#include
#include
#include
#include
#include
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 250010
#define INF 0x7fffffff
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
int v[60],cnt[60];
int a[MAXN],b[MAXN];
int main()
{
//freopen("ceshi.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF)
{
if(n<0) break;
int sum=0;
for(int i=0;i=0;i--)
{
if(a[i]!=0)
{
printf("%d %d\n",sum-i,i);
break;
}
}
}
return 0;
}