T1
HDU1028 Ignatius and the Princess III
题意
求将n拆分成若干整数的方案数。
思路
我们依然考虑用生成函数x^n的系数表示选取的方案数,那么生成函数的每一个乘项的每一项的次方数就代表这个数字是几。我们考虑对于每一个数字,他可以构成的数作为数列建立生成函数,可以列出柿子
这个东西即使化简了也是很难算的,多项式乘法FFT,n这么小直接暴力O(n^3)啊
代码
#include <cstdio>
using namespace std;
int a[500],b[500],n;
int main()
{
while (scanf("%d",&n)!=EOF)
{
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<=n;k+=i)
b[j+k]+=a[j];
for (int j=0;j<=n;j++) a[j]=b[j],b[j]=0;
}
printf("%d\n",a[n]);
}
}
T2
题意
求将n划分成若干个完全平方数的方案数。
思路
依旧沿袭上一个题目的思路,只不过现在不是所有数字都能用了,只有平方数才能用,我们预处理出平方数,用数列表示:光用这一个数字能不能凑出来,跟上个题一样,不写了
T3
HDU1085 Holding Bin-Laden Captive!
题意
有a个1,b个2,c个5,问最小的无法组合出的数。
思路
看到题面的我就是一激灵,NOIP的惨案。。
这个生成函数是个有限数列了
那么我们O(n^2)暴力展开看看哪个系数是0就好了
T4
题意
有n种东西,每一个的权值为v,有m个。将这些东西分成两拨,让权值和尽量接近。
思路
我们根据套路列出柿子,指数是价值,数列是这个价值可以凑出的数
然后求出系数之后从总价值/2开始找,距中点最近的且系数不为0的价值
事实上只需要运行到总价值/2的位置就好了,时间复杂度O(n m sum)
但是因为sum是一点点累加的所以并不会T?!
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[300000],b[300000];
int main()
{
int n;
while (scanf("%d",&n) && n>0)
{
int sum=0,v,m; scanf("%d%d",&v,&m);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));sum=v*m;
for (int i=0;i<=m*v;i+=v) a[i]=1;
for (int i=2;i<=n;i++)
{
scanf("%d%d",&v,&m);
for (int j=0;j<=sum;j++)
for (int k=0;k<=m*v;k+=v) b[j+k]+=a[j];
sum+=v*m;
for (int j=0;j<=sum;j++) a[j]=b[j],b[j]=0;
}
for (int i=sum/2;i>=0;i--)
if (a[i]) {printf("%d %d\n",sum-i,i);break;}
}
}