(File IO): input:hack.in output:hack.out
时间限制: 3000 ms 空间限制: 262144 KB 具体限制
Goto ProblemSet
题目描述
马上就要结束了!
已经通过做题得到了
分。但他惊讶地发现,房间里的其他选手也都解决了最难的题。
根据经验断定大多数的选手都会
的!当然,除去
最高的选
。在此之前,
想要
他们来使他的得分更高。除了
,房间里有
个选手,他们已经被按照
从小到大排序了(所以
是排在第
个的选手)。当
成功
了第
个选手时,他会获得
分的收入。你可以假设
技术高超,百发百中,可以
除了
和自己以外的所有选手,而且在此期间没有其他选手干扰。
由于
有着谦虚的美德,他不想让自己的得分太高。
想要知道,存在着多少种不同的选择一些人
的方案,使得他的得分在
和
之间。
显然答案会很大,请输出答案对
取模后的结果。
输入
一行,四个整数
分别表示
个选手,当前分数为
,希望得分在
到
之间
输出
输出一行,方案数
样例输入
Sample Input1:
3 0 1 2
Sample Input2:
5 13 14 17
Sample Input3:
100 0 23 59
样例输出
Sample Output1:
2
Sample Output2:
6
Sample Output3:
90567
数据范围限制
对于
的数据:
;
对于
的数据:
;
对于
的数据:
;
解题思路
思路:
首先,设
为前
个数选了若干个的和为
的方案数,
那么容易推出
但是,这样做空间复杂度为
,绝对会炸
所以,发现前
个数的和为
令
,则
只有根号
级别,那么说明最多选根号
个数
故可以转成
(为选了i个数和为j的方案数)
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int INF=998244353;
int n,c,l,r,ans,f[500][100100];
int main(){
freopen("hack.in","r",stdin);
freopen("hack.out","w",stdout);
scanf("%d%d%d%d",&n,&c,&l,&r);
l-=c;
r-=c;
f[0][0]=1;
for(int i=1;i*(i-1)/2<n;i++)
for(int j=i*(i-1)/2;j<=r;j++){
f[i][j]=(f[i][j-i]+f[i-1][j-i])%INF;
if(j>=l)
ans=(ans+f[i][j])%INF;
}
printf("%d",ans);
}