Codeforces Round #493 (Div. 2) Problem D. Roman Digits

链接

http://codeforces.com/contest/998/problem/D

题目大意

有四种不同的字符,权值分别为 1,5,10,50 1 , 5 , 10 , 50 ,你要组成长度为 n n 的字符串,字符串的权值是所有字符的权值之和,问你有多少种可能的权值之和(每种字符的使用次数都可以是[0,n]中任何数字)。

题解

这题真心不好想
四种权值我们先把他变成{0,4,9,49},这样或许能简单一些
如果只有 0 0 ,那么显然权值之和只有一种
如果只有0,4那么显然答案是 n+1 n + 1
如果只有 0,4,9 0 , 4 , 9 ,考虑下什么时候会重复,显然 4 4 9 9 9 4可以互相取代(其他位置都填 0 0 ),这两种方案只能保留一种,另一种不统计,显然要保留4 9 9 ,因为这样可以剩下更多的空位,从而组成更多的权值。显然当4的个数大于等于 9 9 时,我总能选出9 4 4 4 9 9 来取代,因此4只能枚举到 8 8
现在考虑49,可以沿用同样的思路,假设选择 i i 4 j j 9,如果另一种方案 (i,j) ( i ′ , j ′ ) 使得 4i+9j=4i+9j+49k 4 i + 9 j = 4 i ′ + 9 j ′ + 49 k ,那么 (i,j) ( i ′ , j ′ ) 再加上 k k 49就可以完全取代 (i,j) ( i , j ) 这种方案,沿用上面的思路,我们当然保留 i+j i + j 较小的一组。这样是仅考虑了 49 49 的出现对方案的影响,但是不难发现当 k=0 k = 0 时就包含了 4 4 9互相代替的方案。
那么最终的算法就是,枚举 0i,j48 0 ≤ i , j ≤ 48 ,用 fk f k 表示 4i+9j=k(mod49) 4 i + 9 j = k ( mod 49 ) 的最小的 i+j i + j 是多少,那么答案就是

ans=i=048(nai+1) a n s = ∑ i = 0 48 ( n − a i + 1 )

有人说打标发现答案到后面是公差为 49 49 的等差数列,那这个其实很显然,当 n n 比较大的时候,ai会一直不变,变得只有式子里的 n n ,显然当n增加 1 1 时,答案增加49

代码

#include <cstdio>
#include <algorithm>
#define ll long long
#define inf 0x3f3f3f3fll
using namespace std;
int main()
{
    ll n, ans=0, i, j, f[49];
    scanf("%I64d",&n);
    for(i=0;i<49;i++)f[i]=inf;
    for(i=0;i<=min(8ll,n);i++)for(j=0;j<=min(48ll,n) and i+j<=n;j++)f[(4*i+9*j)%49]=min(i+j,f[(4*i+9*j)%49]);
    for(i=0;i<=48;i++)if(f[i]!=inf)ans+=n-f[i]+1;
    printf("%I64d",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值