Codeforces Round #493 (Div. 1) B - Roman Digits

题意:1,5,10,50四种硬币不限量,问用刚好n个硬币可以凑出多少种不同的数,n<=1e9

分析:本题的一大难点在于同一个数可能被不同的硬币所表示,可以通过如下方法化简:

由于硬币数量固定,我们可以把所有硬币的价值-1,使得价值变为{0,4,9,49}

考虑如果我们选了(49+x)个4或者9,可以将其换成x个4或9,将49的倍数部分用0和49进行填充

所以我们可以枚举4和9各选i,j个,i/j取[0,min(n,48)]之间且i+j<=n时可以得到的对于49的余数

设sum = 4*i + 9*j, 剩下的位置只选择0或49,可以在sum到sum+(n-i-j)*49之间每隔49个都能取一个

这样对于每种49的余数处理出最大的可行区间即可

#include<bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second
#define mk make_pair
#define sc(x) scanf("%d", &x)
#define pb push_back
#define ABS(x) ((x)<0?(-x):(x));
typedef long long LL;
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 1e6+10;

int n, L[50], R[50];

int main(){
    freopen("lych.in", "r", stdin);
    for(int i = 0; i < 49; i++) L[i] = INF, R[i] = -INF;
    sc(n);
    L[0] = 0;
    R[0] = n;
    for(int i = 0; i <= min(n,49); i++){
        for(int j = 0; j <= min(n,49); j++){
            if(i+j > n) continue;
            int sum = (i*4+j*9);
            int r = sum%49, b = sum/49;
            L[r] = min(L[r], b);
            R[r] = max(R[r], b+n-i-j);
        }
    }
    LL ans = 0;
    for(int i = 0; i < 49; i++){
        if(L[i] >= INF) continue;
        //printf("L[%d]:%d, R[%d]:%d\n", i, L[i], i, R[i]);
        ans += R[i]-L[i]+1;
    }
    cout << ans << endl;
   return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值