2024/3/16 GESP-6级 A题

题目

  题目大意

       小A在玩游戏,有n, a, b, c四个数。他要进行若干次操作。每次操作分为两种:1.n - a  2.n - b     当n < c时,终止操作。请问共有几种不同的操作方法(当两次操作的操作次数不同,或操作次       数相同时,某一时刻的操作不同,则认为这是两种不同的操作方式。121与112是两种操作方法)

  输入一
1 1 1 1
  输出一 
1
  输入二
114 51 4 1
  输出二 
176
   数据范围

    1 <= a,b,c <= n

    对于20%的数据 a=b=c=1, n <= 30

    对于40%的数据 c=1 a <= 1000

    对于所有数据 1<=a, b, c, n<=2e5

分析

    在看到题目时,第一时间想到的是枚举1类操作和2类操作的数量,用乘法原理加快速幂算。写完之后发现答案始终少一点。在草稿纸上写写画画后,发现了问题。以输入二为例:

    4 4 4 ...... 4 51(28个4,1个51)是可行的方案,但是在枚举过程中枚举不出。原因就在于我们直接确定了操作的数量,直接按照正正好取到n的情况计算得出答案,算不到上述情况。

    突然想到我们可以反向枚举。类似于递推,从n=1推起,一直退到n=n,很像斐波那契数列,初始值为1~min(a, b),按照斐波那契数列的做法   f[i] = f[max(0, i-a)] + f[max(0, i-b)] 为递推式,就可以求啦。

解答

#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5;
int n, a, b, c, t[N]; 

int main() {
	cin >> n >> a >> b >> c;
	if (a > b) swap(a, b); //习惯把大的放前面,不放也可以
	if (n == c) { //特判n=c时无法操作,也就是只有一种操作
		cout << "1" << endl;
		return 0;
	}
    
	for (int i = 0; i <= c; ++ i)
		t[i] = 1;
	//初始化

	for (int i = c + 1; i <= n; ++ i) {
		int u = i - a;
		int v = i - b;
		if (u < 0) u = 0; //以防数组下标越界
		if (v < 0) v = 0; //同上
		t[i] = t[v] + t[u];
	}
	
	cout << t[n] << endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值