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