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

链接

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

题目大意

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

题解

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

a n s = i = 0 48 ( n a i + 1 )

有人说打标发现答案到后面是公差为 49 的等差数列,那这个其实很显然,当 n 比较大的时候, a i 会一直不变,变得只有式子里的 n ,显然当 n 增加 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;
}

猜你喜欢

转载自blog.csdn.net/fsahfgsadhsakndas/article/details/80908697