AT_abc463_g 题解
非常巧妙。
个人认为很有趣的一个题喵。
先让
首先我们要注意到的一个点,就是如果你走的时候一直没有超过
那么等价于就是说,如果某个询问 这个从样例的第四组输入也能看得出来。
那么排除掉前面
但是这还有对奇偶性的限制以及后面的除法部分,未免太难受了,令
那么对于一组
这个东西暴力做肯定是不行的,但我们可以考虑莫队。不会?请左转莫队模板学习。这里考虑的是一个前缀
但是不同查询的
发现这个
然后你就会得到两坨式子,虽然不好看,但是能
- 从
n 变为n' = n+1 : -
- 从
n 变为n' = n-1 : -
可以发现加和减的变化是相反的,因此理解了一边也一定能理解另一边。如果你实在推不出为何,可以从最终式子代入数值反推回原始式子。但不管你是怎么推的,一定一定要记得在必要时用上帕斯卡公式!!
那么就做完了,套一个莫队的板子即可。顺便推销我的莫队模板题题解。
取模时如果出现减法一定要加上模数再取模啊!!
::::success[code && submission]
#include<bits/stdc++.h>
#define LL long long
#define UInt unsigned int
#define ULL unsigned long long
#define LD long double
#define pii pair<int,int>
#define pLL pair<LL,LL>
#define pDD pair<LD,LD>
#define fr first
#define se second
#define pb push_back
#define isr insert
#define _i128 __int128
using namespace std;
const int N = 2e5+5;
const int up = 200000;
const LL MOD = 998244353;
struct query{LL n,m,x,d,id;}q[N];
LL Q,sq,ans[N];
LL fac[N],inv[N],inv2;
LL nown,nowm,Ansk,Ans=1;
LL read(){
LL su=0,pp=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')pp=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){su=su*10+ch-'0';ch=getchar();}
return su*pp;
}
LL QP(LL x,LL y=MOD-2){
LL as=1;
while(y){
if(y&1)as=as*x%MOD;
x=x*x%MOD,y>>=1;
}return as;
}
void init_(){
fac[0]=1,inv[0]=1;inv2=QP(2);
for(LL i=1;i<=up;i++)
fac[i]=fac[i-1]*i%MOD;
inv[up]=QP(fac[up]);
for(LL i=up-1;i>=1;i--)
inv[i]=inv[i+1]*(i+1)%MOD;
return;
}
bool cmp(query q1,query q2){
if(q1.n/sq!=q2.n/sq)return q1.n<q2.n;
if((q1.n/sq)&1)return q1.m<q2.m;
else return q1.m>q2.m;
}
LL C(LL x,LL y){
if(x<0||y<0||x<y)return 0;
LL res=fac[x]*inv[x-y]%MOD;
return res*inv[y]%MOD;
}
void addN(){
Ansk=((2*Ansk+Ans)%MOD-(nowm+1)*C(nown,nowm)%MOD+MOD)%MOD;
Ans=(2*Ans%MOD-C(nown,nowm)+MOD)%MOD;
return;
}
void delN(){
Ans=(Ans+C(nown-1,nowm))%MOD*inv2%MOD;
Ansk=(Ansk-Ans+MOD+(nowm+1)*C(nown-1,nowm)%MOD)%MOD*inv2%MOD;
return;
}
void addM(){
Ans=(Ans+C(nown,nowm+1))%MOD;
Ansk=(Ansk+(nowm+1)*C(nown,nowm+1)%MOD)%MOD;
return;
}
void delM(){
Ans=(Ans-C(nown,nowm)+MOD)%MOD;
Ansk=(Ansk-nowm*C(nown,nowm)%MOD+MOD)%MOD;
return;
}
int main(){
Q=read(),sq=sqrt(up);init_();
for(int i=1;i<=Q;i++){
q[i].n=read(),q[i].x=abs(read());
q[i].d=q[i].n-q[i].x,q[i].m=(q[i].d-1)/2;
q[i].id=i;
}sort(q+1,q+Q+1,cmp);
for(int i=1;i<=Q;i++){
if(q[i].x>=q[i].n){
ans[q[i].id]=q[i].x%MOD;
continue;
}
while(nown<q[i].n)addN(),nown++;
while(nown>q[i].n)delN(),nown--;
while(nowm<q[i].m)addM(),nowm++;
while(nowm>q[i].m)delM(),nowm--;
LL res=QP(inv2,q[i].n-1)*(q[i].d*Ans%MOD-2*Ansk%MOD+MOD)%MOD;
ans[q[i].id]=(q[i].x+res)%MOD;
}
for(int i=1;i<=Q;i++)cout<<ans[i]<<"\n";
return 0;
}
::::
如果本篇题解对你有帮助的话,麻烦你点一个小小的赞,真是太感谢啦!