链接
http://codeforces.com/contest/998/problem/D
题目大意
有四种不同的字符,权值分别为 1,5,10,50 1 , 5 , 10 , 50 ,你要组成长度为 n n 的字符串,字符串的权值是所有字符的权值之和,问你有多少种可能的权值之和(每种字符的使用次数都可以是[0,n]中任何数字)。
题解
这题真心不好想
四种权值我们先把他变成,这样或许能简单一些
如果只有
0
0
,那么显然权值之和只有一种
如果只有那么显然答案是
n+1
n
+
1
如果只有
0,4,9
0
,
4
,
9
,考虑下什么时候会重复,显然
4
4
个和
9
9
个可以互相取代(其他位置都填
0
0
),这两种方案只能保留一种,另一种不统计,显然要保留个
9
9
,因为这样可以剩下更多的空位,从而组成更多的权值。显然当的个数大于等于
9
9
时,我总能选出个
4
4
用个
9
9
来取代,因此只能枚举到
8
8
。
现在考虑,可以沿用同样的思路,假设选择
i
i
个,
j
j
个,如果另一种方案
(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
个就可以完全取代
(i,j)
(
i
,
j
)
这种方案,沿用上面的思路,我们当然保留
i+j
i
+
j
较小的一组。这样是仅考虑了
49
49
的出现对方案的影响,但是不难发现当
k=0
k
=
0
时就包含了
4
4
与互相代替的方案。
那么最终的算法就是,枚举
0≤i,j≤48
0
≤
i
,
j
≤
48
,用
fk
f
k
表示
4i+9j=k(mod49)
4
i
+
9
j
=
k
(
mod
49
)
的最小的
i+j
i
+
j
是多少,那么答案就是
有人说打标发现答案到后面是公差为 49 49 的等差数列,那这个其实很显然,当 n n 比较大的时候,会一直不变,变得只有式子里的 n n ,显然当增加 1 1 时,答案增加
代码
#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;
}