题解 P5278 【算术天才⑨与等差数列】
NaCly_Fish · · 题解
这是一种乱搞做法,非正解。
这里用了hash的思想,类比这个题目:
P3792 由乃与大母神原型和偶像崇拜
我们可以考虑维护区间平方和,由于出题人非常良心,所以这个方法没有被卡掉。
对于可以重排为公差为
注意这个只是充分条件,不具有必要性。
然后我们把等式右边展开一下
式子展开到这里,就可以直接计算了。
区间最小值
最后,把算出来的结果与区间实际平方和进行比较。
如果一样,就输出 Yes,否则输出 No。
注意平方和的结果可能很大,所以我们随便找个质数膜一下,几乎不会影响到答案的正确性。
然后我的非正解就水过了这个题 23333
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#define int long long
#define N 300003
#define reg register
#define p 998244353
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((l+r)>>1)
#define inf 0x3f3f3f3f
using namespace std;
int w[N],a[N<<2],minn[N<<2],s[N<<2];
int n,q,key;
inline void read(int &x);
inline int power(int a,int t);
void build(int l,int r,int u);
inline void pushup(int u);
inline int min(int x,int y);
void modify(int t,int k,int l,int r,int u);
int qmin(int nl,int nr,int l,int r,int u);
int qsqr(int nl,int nr,int l,int r,int u);
inline int inv(int x);
signed main(){
int op,l,r,x,y,k,t,sum,sqr;
int len,inv6;
inv6 = inv(6);
read(n),read(q);
for(int i=1;i<=n;++i) read(w[i]);
build(1,n,1);
while(q--){
read(op);
if(op==1){
read(x),read(y);
x ^= key,y ^= key;
modify(x,y,1,n,1);
w[x] = y;
}else{
read(l),read(r),read(k);
l ^= key,r ^= key;
k ^= key;
len = r-l+1;
x = qmin(l,r,1,n,1);
sqr = qsqr(l,r,1,n,1);
t = len*x%p*x%p;
t = t+x*k%p*len%p*(len-1)%p;
t %= p;
--len;
sum = k*k%p*(len*(len+1)%p*((len<<1)+1)%p*inv6%p)%p;
t = (t+sum)%p;
if(t!=sqr){
printf("No\n");
continue;
}
printf("Yes\n");
++key;
}
}
return 0;
}
inline int inv(int x){
return power(x,p-2);
}
int qsqr(int nl,int nr,int l,int r,int u){
if(nl<=l&&r<=nr) return s[u];
int res = 0;
if(nl<=mid) res += qsqr(nl,nr,l,mid,ls);
if(nr>mid) res += qsqr(nl,nr,mid+1,r,rs);
return res%p;
}
int qmin(int nl,int nr,int l,int r,int u){
if(nl<=l&&r<=nr) return minn[u];
int res = inf;
if(nl<=mid) res = min(res,qmin(nl,nr,l,mid,ls));
if(nr>mid) res = min(res,qmin(nl,nr,mid+1,r,rs));
return res;
}
void modify(int t,int k,int l,int r,int u){
if(l==r){
a[u] = minn[u] = k;
s[u] = k*k%p;
return;
}
if(t<=mid) modify(t,k,l,mid,ls);
else modify(t,k,mid+1,r,rs);
pushup(u);
}
inline void pushup(int u){
a[u] = (a[ls]+a[rs])%p;
s[u] = (s[ls]+s[rs])%p;
minn[u] = min(minn[ls],minn[rs]);
}
void build(int l,int r,int u){
if(l==r){
a[u] = minn[u] = w[l];
s[u] = w[l]*w[l]%p;
return;
}
build(l,mid,ls);
build(mid+1,r,rs);
pushup(u);
}
inline int min(int x,int y){
return x<y?x:y;
}
inline void read(int &x){
x = 0;
char c = getchar();
while(c<'0'||c>'9') c = getchar();
while(c>='0'&&c<='9'){
x = (x<<3)+(x<<1)+(c^48);
c = getchar();
}
}
inline int power(int a,int t){
int res = 1;
while(t){
if(t&1) res = res*a%p;
a = a*a%p;
t >>= 1;
}
return res;
}