找单词
Problem Description
假设有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认为是同一个单词)。
Input
输入首先是一个整数N,代表测试实例的个数。
然后包括N行数据,每行包括26个<=20的整数x1,x2,…x26.
Output
对于每个测试实例,请输出能找到的总价值<=50的单词数,每个实例的输出占一行。
Sample Input
2
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
9 2 6 2 10 2 2 5 6 1 0 2 7 0 2 2 7 5 10 6 10 2 10 6 1 9
Sample Output
7
379297
母函数的基本操作
假设用x表示字母,x的指数表示总价值
可以得到
x
1
x_1
x1个字母
A
A
A 可以用多项式
:
1
+
x
1
+
x
2
+
⋯
:\quad1+x^1+x^2+\cdots
:1+x1+x2+⋯
x
2
x_2
x2个字母
B
B
B 可以用多项式
:
1
+
x
2
+
x
4
+
⋯
:\quad1+x^2+x^4+\cdots
:1+x2+x4+⋯
x
3
x_3
x3个字母
C
C
C 可以用多项式
:
1
+
x
3
+
x
6
+
⋯
:\quad1+x^3+x^6+\cdots
:1+x3+x6+⋯
⋮
⋮
\qquad\vdots \\ \qquad\vdots
⋮⋮
x
26
x_{26}
x26个字母
Z
Z
Z 可以用多项式
:
1
+
x
1
+
x
26
+
⋯
:\quad1+x^1+x^{26}+\cdots
:1+x1+x26+⋯
构造母函数如下:
G
(
x
)
=
(
1
+
x
1
+
⋯
 
)
(
1
+
x
2
+
⋯
 
)
⋯
(
1
+
x
26
+
⋯
 
)
G(x) =(1+x^1+\cdots)(1+x^2+\cdots)\cdots(1+x^{26}+\cdots)
G(x)=(1+x1+⋯)(1+x2+⋯)⋯(1+x26+⋯)
可得到:
G
(
x
)
=
1
+
c
1
x
+
c
2
x
2
+
⋯
\Large G(x) = 1+c_1x+c_2x^2+\cdots
G(x)=1+c1x+c2x2+⋯
其中 c i ∗ x i c_i*x^{i} ci∗xii是价值, c i c_i ci是方案数
我们只需要统计 ∑ i = 1 50 c i \sum_{i=1}^{50}\ c_i ∑i=150 ci就能得出结果
#include<bits/stdc++.h>
using namespace std;
int C1[55];//系数;
int C2[55];//暂时存放
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(C1,0,sizeof(C1));
memset(C2,0,sizeof(C2));
int num;C1[0]=1;
for(int i=1;i<=26;++i)
{
scanf("%d",&num);
if(!num) continue;
for(int j=0;j<51;++j)
for(int k=0;k<=num&&k*i+j<51;++k)//因为只要前五十项的系数...
C2[k*i+j] += C1[j];//对于每一个x^(k*i+1)项,它的系数都要加上前面与它相乘x^j项的系数
memcpy(C1,C2,sizeof(C2));//将C2赋值给C1
memset(C2,0,sizeof(C2));
}
int ans = 0;
for(int i=1;i<51;++i) ans += C1[i];
printf("%d\n",ans);
}
return 0;
}