找单词 母函数初级应用
本题是最简单的母函数问题,请看母函数初涉
题目链接
分析
刚看到此题是第一个想到的是用搜索来解或者用动态规划的思路,之后学了母函数发现此题是最简单的母函数的应用。有了母函数的思想后就是代码的实现的问题,母函数的关键一点就是如何用代码展开多项式,下面代码中给出详细的注释。。。。。
#include<stdio.h>
#include<vector>
#include<string.h>
#include<iostream>
using namespace std;
int main()
{
int T;
scanf("%d",&T);
int c1[100],c2[100];//c1放的是当前表达式的系数 c[i]=n 的意义是x的i次方的系数为n,c2保存的是当前表达式与下一个表达式运算的临时结果
vector<int>sum,value;//sum[i]是每个字母有多少个,value放的是字母的权值
while(T--)
{
sum.clear();
value.clear();
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
for(int i=1; i<=26; i++)
{
int temp=0;
scanf("%d",&temp);//一次输入26个字母他每一个的个数
if(temp!=0)//个数为零的就不用计算了
{
sum.push_back(temp);
value.push_back(i);
}
}
int len=sum.size();//一共有多少个 个数不为零的字母
if(len==0)
printf("0\n");
else
{
//首先c1保存的是第一项表达式每个x的系数,,他们的初始值都是1
//并且题目要求权值不超过50,同时第一个表达式的个数已知sum[0],
//权重已知value[0],那么第一个字母可能取得的权重最大为sum[0]*value[0]
for(int i=0; i<=50&&i<=sum[0]*value[0]; i+=value[0])
c1[i]=1;
for(int i=1; i<len; i++)//从第二个表达式开始循环 此时c1[]数组里面已经放的是第一项表达式的系数
{
//遍历c1[]数组用的,,,题目要求最大权重为50 ,c1[]放的是当前表达式
//每一项的系数,这个表达式在循环之前保存的是第一项表达式的系数,经过第一遍循环保存的则是
//第一项表达式与第二项表达式相乘之后的各项系数一次类推
for(int j=0; j<=50; j++)
//k+j代表的是c1中的x^j y与 x^k 相乘等于 x^(k+j)
for(int k=0; k+j<=50&&k<=value[i]*sum[i]; k+=value[i])
c2[k+j]+=c1[j];//合并同类项,,,
for(int i=0; i<=50; i++)
{
c1[i]=c2[i];//乘完这一项之后把c1中的值刷新
c2[i]=0;//重新置为0
}
}
int res=0;
for(int i=1; i<=50; i++)
res+=c1[i];//把每一项的系数加起来 就是一共有多少种选择方案
printf("%d\n",res);
}
}
return 0;
}
梦里不知身是客,一晌贪欢。