题目:https://cn.vjudge.net/contest/178527#problem/A
假设有x1个字母A, x2个字母B,..... x26个字母Z,同时假设字母A的价值为1,字母B的价值为2,..... 字母Z的价值为26。那么,对于给定的字母,可以找到多少价值<=50的单词呢?单词的价值就是组成一个单词的所有字母的价值之和,比如,单词ACM的价值是1+3+14=18,单词HDU的价值是8+4+21=33。(组成的单词与排列顺序无关,比如ACM与CMA认为是同一个单词)。
输入首先是一个整数N,代表测试实例的个数。
然后包括N行数据,每行包括26个<=20的整数x1,x2,.....x26.
思路:有个数限制的母函数,也可以用背包。
#include<iostream>
#include<string.h>
using namespace std;
#define maxn 10000
int c1[maxn], c2[maxn],num[30];
int main()
{
int T,i,j;
cin >> T;
while (T--)
{
memset(c1, 0, sizeof(c1));
memset(c2, 0, sizeof(c2));
for ( i = 1; i <= 26; i++)
cin >> num[i];
for (i = 0; i <= num[1]&&(i<=50); i++)
c1[i] = 1;
for (i = 2; i <= 26; i++)//表示第i个式子
{
for (j = 0; j <= 50; j++)//表示第j项目
{
for (int k = 0; (k <= num[i]*i) &&( k + j <= 50); k+=i) //注意每种字母 //数量对应
c2[j + k] += c1[j];
}
for (j = 0; j <= 50; j++)
{
c1[j] = c2[j];
c2[j] = 0;
}
}
long long ans = 0;
for (j = 1; j <= 50; j++)
ans += c1[j];
cout << ans << endl;
}
return 0;
}
背包:
这里因为每个字母有个数限值,所以是多重背包的类型,
#include <bits/stdc++.h>
using namespace std;
#define maxV 51
int dp[maxV],a[maxV];
int main()
{
int N;
cin>>N;
while(N--)
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=26;i++)
cin>>a[i];
dp[0]=1;
for(int i=1;i<=26;i++)
for(int j=maxV;j>=i;j--)//i代表价值
{
for(int k=1;k<=a[i]&&k*i<=j;k++)
dp[j]+=dp[j-k*i];
}
long long ans=0;
for(int i=1;i<=50;i++)
ans+=dp[i];
cout<<ans<<endl;
}
return 0;
}