P8894 「UOI-R1」求和 题解
sumlimits{s1={p1}}^{q1}sumlimits{s2={p2}}^{q2}sumlimits{s3={p3}}^{q3} cdotssumlimits{sn={pn}}^{qn}ma…
首先拿到这个式子,结合数据范围,模拟肯定超时了。这种时候一般需要把题目抽象出来,搞懂这个东西在说什么。
既然正面想不通,就从反面想,首先这个式子一串求和就是在干一个事情,每个区间选一个元素,把每种组合跑一遍,然后求出选出的元素中最大的一个,累加到答案中。那么,什么时候 才能对答案做出贡献?肯定是 是所有选出元素最大的时候,看似废话的一句话,实际就做完了题。考虑枚举每一个 ,对于每个 ,计算有多少个方案使得 为最大。根据乘法原理,可得,使得最大值小于等于 的方案数量为 记为 ,但是现在要求得出最大值为 的方案树,怎么办?考虑将方案结果小于 剔除,也就是 ,就求得了使得 为最大的方案数。最后累加 即可。
AC code 码风很丑,各位见谅。
#include <cstdio>
#include <algorithm>
#define INPUT_DATA_TYPE long long
#define OUTPUT_DATA_TYPE long long
struct node{
int l,r;
}arr[5010];
long long ansleq[5010];
INPUT_DATA_TYPE read();
void print(OUTPUT_DATA_TYPE x);
int main(){
register int i,j,min=0,max=0;
register long long temp,ans=0;
int n=read();
for(i=0;i<n;++i){
arr[i].l=read();
arr[i].r=read();
min=std::max(min,arr[i].l);//精确控制上下界
max=std::max(max,arr[i].r);
}
for(i=min;i<=max;++i){
temp=1;
for(j=0;j<n;++j)
temp=temp*(std::min(i,arr[j].r)-arr[j].l+1)%998244353;
ansleq[i]=temp;
}
for(i=min;i<=max;++i) ans=(ans+(((ansleq[i]-ansleq[i-1]))*i%998244353)+998244353)%998244353;//注意ansleq[i]-ansleq[i-1]可能为负数
print(ans);
return 0;
}
INPUT_DATA_TYPE read(){
register INPUT_DATA_TYPE x=0;register char f=0,c=getchar();
while(c<'0'||'9'<c)f=(c=='-'),c=getchar();//?=if,:=else
while('0'<=c&&c<='9')x=(x<<3)+(x<<1)+(c&15),c=getchar();
return f?-x:x;
}
void print(OUTPUT_DATA_TYPE x){
register char s[20];
register int i=0;
if(x<0){
x=-x;
putchar('-');
}
if(x==0){
putchar('0');
return;
}
while(x){
s[i++]=x%10;
x/=10;
}
while(i){
putchar(s[--i]+'0');
}
return;
}谢谢你,读到这里。
本文同步自洛谷专栏,保留原始正文与发布时间。在洛谷查看原文 ↗