杭电ACM-LCY算法进阶培训班-专题训练(母函数及应用)

杭电ACM-LCY算法进阶培训班-专题训练(母函数及应用)

Ignatius and the Princess III

Problem Description

“Well, it seems the first problem is too easy. I will let you know how foolish you are later.” feng5166 says.

"The second problem is, given an positive integer N, we define an equation like this:
N=a[1]+a[2]+a[3]+…+a[m];
a[i]>0,1<=m<=N;
My question is how many different equations you can find for a given N.
For example, assume N is 4, we can find:

4 = 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;

so the result is 5 when N is 4. Note that “4 = 3 + 1” and “4 = 1 + 3” is the same in this problem. Now, you do it!"

Input

The input contains several test cases. Each test case contains a positive integer N(1<=N<=120) which is mentioned above. The input is terminated by the end of file.

Output

For each test case, you have to output a line contains an integer P which indicate the different equations you have found.

Sample Input

4
10
20

Sample Output

5
42
627

思路:

样例中,n=4时,可以构造: ( 1 + x + x 2 + x 3 + x 4 ) ( 1 + x 2 + x 4 ) ( 1 + x 3 ) ( 1 + x 4 ) (1+x+x^2+x^3+x^4)(1+x^2+x^4)(1+x^3)(1+x^4) (1+x+x2+x3+x4)(1+x2+x4)(1+x3)(1+x4)
按照这个格式就可以写出 1 < = n < = 120 1<=n<=120 1<=n<=120的情况了。

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=125;
int n,p[maxn],q[maxn];

int main(){
    while(~scanf("%d",&n)){
        for(int i=0;i<=n;i++)   p[i]=1;
        for(int i=2;i<=n;i++){
            for(int j=0;j<=n;j+=i)
                for(int k=0;k+j<=n;k++)   q[j+k]+=p[k];
            for(int j=0;j<=n;j++)   p[j]=q[j],q[j]=0;
        }
        printf("%d\n",p[n]);
        memset(p,0,sizeof(p));
    }
}

Square Coins

Problem Description

People in Silverland use square coins. Not only they have square shapes but also their values are square numbers. Coins with values of all square numbers up to 289 (=17^2), i.e., 1-credit coins, 4-credit coins, 9-credit coins, …, and 289-credit coins, are available in Silverland.
There are four combinations of coins to pay ten credits:

ten 1-credit coins,
one 4-credit coin and six 1-credit coins,
two 4-credit coins and two 1-credit coins, and
one 9-credit coin and one 1-credit coin.

Your mission is to count the number of ways to pay a given amount using coins of Silverland.

Input

The input consists of lines each containing an integer meaning an amount to be paid, followed by a line containing a zero. You may assume that all the amounts are positive and less than 300.

Output

For each of the given amount, one line containing a single integer representing the number of combinations of coins should be output. No other characters should appear in the output.

Sample Input

2
10
30
0

Sample Output

思路:

可以构造 ( 1 + x + x 2 + x 3 + . . . ) ( 1 + x 4 + x 8 + . . . ) ( 1 + x 9 + x 18 + . . . ) . . . ( 1 + x 289 + x 578 + . . . ) (1+x+x^2+x^3+...)(1+x^4+x^8+...)(1+x^9+x^{18}+...)...(1+x^{289}+x^{578}+...) (1+x+x2+x3+...)(1+x4+x8+...)(1+x9+x18+...)...(1+x289+x578+...)

1
4
27
#include<cstdio>
using namespace std;
const int maxn=305;
int n,p[maxn],q[maxn];

int main(){
    while(scanf("%d",&n),n){
        for(int i=0;i<=n;i++)   p[i]=1;
        for(int i=2;i<=n;i++){
            for(int j=0;j<=n;j+=i*i)
                for(int k=0;k+j<=n;k++) q[j+k]+=p[k];
            for(int j=0;j<=n;j++)   p[j]=q[j],q[j]=0;
        }
        printf("%d\n",p[n]);
    }
}

Holding Bin-Laden Captive!

Problem Description

We all know that Bin-Laden is a notorious terrorist, and he has disappeared for a long time. But recently, it is reported that he hides in Hang Zhou of China!
“Oh, God! How terrible! ”

在这里插入图片描述
Don’t be so afraid, guys. Although he hides in a cave of Hang Zhou, he dares not to go out. Laden is so bored recent years that he fling himself into some math problems, and he said that if anyone can solve his problem, he will give himself up!
Ha-ha! Obviously, Laden is too proud of his intelligence! But, what is his problem?
“Given some Chinese Coins (硬币) (three kinds-- 1, 2, 5), and their number is num_1, num_2 and num_5 respectively, please output the minimum value that you cannot pay with given coins.”
You, super ACMer, should solve the problem easily, and don’t forget to take $25000000 from Bush!

Input

Input contains multiple test cases. Each test case contains 3 positive integers num_1, num_2 and num_5 (0<=num_i<=1000). A test case containing 0 0 0 terminates the input and this test case is not to be processed.

Output

Output the minimum positive value that one cannot pay with given coins, one line for one case.

Sample Input

1 1 3
0 0 0

Sample Output

4

思路:

初始化p[0]=1,然后根据输入的硬币上限构造母函数,最后查找第一个不能组成的金额。

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=8005;
int a[3]={1,2,5},num[3],p[maxn],q[maxn];

int main(){
    while(scanf("%d%d%d",&num[0],&num[1],&num[2]),num[0]|num[1]|num[2]){
        p[0]=1;
        for(int i=0;i<3;i++){
            for(int j=0;j<=a[i]*num[i];j+=a[i])
                for(int k=0;k<maxn;k++) q[k+j]+=p[k];
            for(int j=0;j<maxn;j++) p[j]=q[j],q[j]=0;
        }
        for(int i=0;i<maxn;i++) if(!p[i]){printf("%d\n",i);break;}
        memset(p,0,sizeof(p));
    }
}

Big Event in HDU

Problem Description

Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don’t know that Computer College had ever been split into Computer College and Software College in 2002.
The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is N (0<N<1000) kinds of facilities (different value, different kinds).

Input

Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 – the total number of different facilities). The next N lines contain an integer V (0<V<=50 --value of facility) and an integer M (0<M<=100 --corresponding number of the facilities) each. You can assume that all V are different.
A test case starting with a negative integer terminates input and this test case is not to be processed.

Output

For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.

Sample Input

2
10 1
20 1
3
10 1 
20 2
30 1
-1

Sample Output

20 10
40 40

思路:

计算总价值all,all/2之下最大的价值就是答案中较小的一个数。

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int maxn=(250000>>1)+5;
int n,v[55],num[55],all,dp[maxn];

int main(){
    while(scanf("%d",&n)&&n>0){
        for(int i=0;i<n;i++){
            scanf("%d%d",&v[i],&num[i]);
            all+=num[i]*v[i];
        }
        for(int i=0;i<n;i++)
            for(int j=all/2;j>=v[i];j--)
                for(int k=1;k<=num[i]&&k*v[i]<=j;k++)
                    dp[j]=max(dp[j],dp[j-k*v[i]]+k*v[i]);
        printf("%d %d\n",all-dp[all/2],dp[all/2]);
        memset(dp,0,sizeof(dp));    all=0;
    }
}

The Balance

Problem Description

Now you are asked to measure a dose of medicine with a balance and a number of weights. Certainly it is not always achievable. So you should find out the qualities which cannot be measured from the range [1,S]. S is the total quality of all the weights.

Input

The input consists of multiple test cases, and each case begins with a single positive integer N (1<=N<=100) on a line by itself indicating the number of weights you have. Followed by N integers Ai (1<=i<=N), indicating the quality of each weight where 1<=Ai<=100.

Output

For each input set, you should first print a line specifying the number of qualities which cannot be measured. Then print another line which consists all the irrealizable qualities if the number is not zero.

Sample Input

3
1 2 4
3
9 2 1

Sample Output

0
2
4 5

思路:

计算总重量S,用母函数求出[1,S]之间不能表示的数。
因为砝码也可以放到天平的另一端,所以要对模板进行小改动。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=105,maxm=1e4+5;
int n,a[maxn],p[maxm],q[maxm],t,sum,ans[maxm],tot;

int main(){
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++)    scanf("%d",&a[i]);
        p[0]=p[a[0]]=1;
        sum=a[0];
        for(int i=1;i<n;i++){
            for(int j=0;j<=sum;j++)
                q[j+a[i]]+=p[j],q[abs(j-a[i])]+=p[j],t=max(t,j+a[i]);
            sum=t;
            for(int j=0;j<=sum;j++)
                p[j]+=q[j],q[j]=0;
        }
        for(int i=0;i<=sum;i++) if(!p[i])   ans[tot++]=i;
        printf("%d\n",tot);
        for(int i=0;i<tot;i++)  printf("%d%c",ans[i],i==tot-1?'\n':' ');
        memset(p,0,sizeof(p));  sum=t=tot=0;
    }
}

Fruit

Problem Description

转眼到了收获的季节,由于有TT的专业指导,Lele获得了大丰收。特别是水果,Lele一共种了N种水果,有苹果,梨子,香蕉,西瓜……不但味道好吃,样子更是好看。

于是,很多人们慕名而来,找Lele买水果。

甚至连大名鼎鼎的HDU ACM总教头 lcy 也来了。lcy抛出一打百元大钞,“我要买由M个水果组成的水果拼盘,不过我有个小小的要求,对于每种水果,个数上我有限制,既不能少于某个特定值,也不能大于某个特定值。而且我不要两份一样的拼盘。你随意搭配,你能组出多少种不同的方案,我就买多少份!”

现在就请你帮帮Lele,帮他算一算到底能够卖出多少份水果拼盘给lcy了。

注意,水果是以个为基本单位,不能够再分。对于两种方案,如果各种水果的数目都相同,则认为这两种方案是相同的。

最终Lele拿了这笔钱,又可以继续他的学业了~

Input

本题目包含多组测试,请处理到文件结束(EOF)。
每组测试第一行包括两个正整数N和M(含义见题目描述,0<N,M<=100)
接下来有N行水果的信息,每行两个整数A,B(0<=A<=B<=100),表示至少要买该水果A个,至多只能买该水果B个。

Output

对于每组测试,在一行里输出总共能够卖的方案数。
题目数据保证这个答案小于 1 0 9 10^9 109

Sample Input

2 3
1 2
1 2
3 5
0 3
0 3
0 3

Sample Output

2
12

思路:

每种水果相当于面值为1的硬币(种类不同),已知每种硬币取量的上下限,求组成m元的组合数。

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=105;
int n,m,a[maxn][2],p[maxn],q[maxn];

int main(){
    while(~scanf("%d%d",&n,&m)){
        for(int i=0;i<n;i++)
            scanf("%d%d",&a[i][0],&a[i][1]);
        for(int i=a[0][0];i<=a[0][1];i++)   p[i]=1;
        for(int i=1;i<n;i++){
            for(int j=a[i][0];j<=a[i][1];j++)
                for(int k=0;k+j<=m;k++)  q[k+j]+=p[k];
            for(int j=0;j<=m;j++)   p[j]=q[j],q[j]=0;
        }
        printf("%d\n",p[m]);
        memset(p,0,sizeof(p));
    }
}

排列组合

Problem Description

有n种物品,并且知道每种物品的数量。要求从中选出m件物品的排列数。例如有两种物品A,B,并且数量都是1,从中选2件物品,则排列有"AB","BA"两种。

Input

每组输入数据有两行,第一行是二个数n,m(1<=m,n<=10),表示物品数,第二行有n个数,分别表示这n件物品的数量。

Output

对应每组数据输出排列数。(任何运算不会超出2^31的范围)

Sample Input

2 2
1 1

Sample Output

2

思路:

指数型母函数的模板题,预处理[1,10]的阶乘,之后用模板就可以了。最后输出结果的时候,由于精度问题,要四舍五入保留整数,而不能向下取整保留整数。

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=11;
int n,m,a[maxn],f[maxn]={1,1};
double p[maxn],q[maxn];

void func(){
    for(int i=2;i<maxn;i++) f[i]=f[i-1]*i;
}

int main(){
    func();
    while(~scanf("%d%d",&n,&m)){
        for(int i=0;i<n;i++)    scanf("%d",&a[i]);
        for(int i=0;i<=a[0];i++)    p[i]=1.0/f[i];
        for(int i=1;i<n;i++){
            for(int j=0;j<=a[i];j++)
                for(int k=0;k+j<=m;k++)
                    q[k+j]+=p[k]/f[j];
            for(int j=0;j<=m;j++)
                p[j]=q[j],q[j]=0;
        }
        printf("%.lf\n",p[m]*f[m]);	//四舍五入保留整数
        memset(p,0,sizeof(p));
    }
}

"红色病毒"问题

Problem Description

医学界发现的新病毒因其蔓延速度和Internet上传播的"红色病毒"不相上下,被称为"红色病毒",经研究发现,该病毒及其变种的DNA的一条单链中,胞嘧啶,腺嘧啶均是成对出现的。
现在有一长度为N的字符串,满足一下条件:

  1. 字符串仅由A,B,C,D四个字母组成;
  2. A出现偶数次(也可以不出现);
  3. C出现偶数次(也可以不出现);

计算满足条件的字符串个数.
当N=2时,所有满足条件的字符串有如下6个:BB,BD,DB,DD,AA,CC.
由于这个数据肯能非常庞大,你只要给出最后两位数字即可.

Input

每组输入的第一行是一个整数T,表示测试实例的个数,下面是T行数据,每行一个整数N(1<=N<2^64),当T=0时结束.

Output

对于每个测试实例,输出字符串个数的最后两位,每组输出后跟一个空行.

Sample Input

4
1
4
20
11
3
14
24
6
0

Sample Output

Case 1: 2
Case 2: 72
Case 3: 32
Case 4: 0

Case 1: 56
Case 2: 72
Case 3: 56

思路:

首先构造母函数为

G ( x ) = ( 1 + x 1 + x 2 2 ! + x 3 3 ! + . . . ) 2 ( 1 + x 2 2 ! + x 4 4 ! + . . . ) 2 G(x) = (1+\frac{x}{1}+\frac{x^2}{2!}+\frac{x^3}{3!}+...)^2(1+\frac{x^2}{2!}+\frac{x^4}{4!}+...)^2 G(x)=(1+1x+2!x2+3!x3+...)2(1+2!x2+4!x4+...)2
由于
e x = 1 + x 1 + x 2 2 ! + x 3 3 ! + . . . e^x = 1+\frac{x}{1}+\frac{x^2}{2!}+\frac{x^3}{3!}+... ex=1+1x+2!x2+3!x3+...
e − x = 1 − x 1 + x 2 2 ! − x 3 3 ! + . . . e^{-x} = 1-\frac{x}{1}+\frac{x^2}{2!}-\frac{x^3}{3!}+... ex=11x+2!x23!x3+...
所以
G ( x ) = e 2 x + ( e x + e − x 2 ) 2 = 1 4 e 2 x ( e 2 x + 2 + e − 2 x ) = 1 4 ( e 4 x + 2 e 2 x + 1 ) = 1 4 { ( 1 + 4 x 1 + ( 4 x ) 2 2 ! + . . . ) + 2 ( 1 + 2 x 1 + ( 2 x ) 2 2 ! + . . . ) + 1 } \begin{aligned} G(x) &=e^{2x}+(\frac{e^x+e^{-x}}2)^2 \\ & = \frac14e^{2x}(e^{2x}+2+e^{-2x}) \\ & =\frac14(e^{4x}+2e^{2x}+1) \\ & =\frac14\{ (1+\frac{4x}{1}+\frac{(4x)^2}{2!}+...)+2(1+\frac{2x}{1}+\frac{(2x)^2}{2!}+...)+1\}\\ \end{aligned} G(x)=e2x+(2ex+ex)2=41e2x(e2x+2+e2x)=41(e4x+2e2x+1)=41{(1+14x+2!(4x)2+...)+2(1+12x+2!(2x)2+...)+1}
x n x^n xn项的系数为 4 n − 1 + 2 n − 1 n ! \frac{4^{n-1}+2^{n-1}}{n!} n!4n1+2n1,由于最终结果需要乘 n ! n! n!所以答案为 4 n − 1 + 2 n − 1 4^{n-1}+2^{n-1} 4n1+2n1

#include<cstdio>
#define int long long
using namespace std;
const int mod=100;
int te,n;

int pow(int a,int b){
    int ans=1;
    while(b){
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod,b>>=1;
    }
    return ans;
}

signed main(){
    while(scanf("%lld",&te),te){
        for(int i=1;i<=te;i++){
            scanf("%lld",&n);
            printf("Case %lld: %lld\n",i,(pow(4,n-1)+pow(2,n-1))%100);
        }
        puts("");
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_51864047

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值