牛客挑战赛39 牛牛的等差数列
LINK:牛牛的等差数列
每次给一个区间加上一个等差数列 求区间和。
不是李超线段树==.
也不是等比数列 所以等差数列具有区间可加性。
考虑一个标记d(p)表示节点p这个区间的等差数列要逐渐加d(p).
这个可以当做懒标记下传。
注意下传的时候 左边对右边的贡献要乘上整个区间 修改也是。
细节挺多。最后值得一提的是模数 发现模数有很多 答案也是爆longlong的 不可能维护对应那么多模数的答案。
考虑对他们的乘积取模 他们乘积也不算很大 最后再对某个模数单独取模 正确性显然。
等差数列求和时 因为这个东西还是可能爆longlong 所以求出2的逆元 不需要exgcd 因为2和mod互质 且mod的欧拉函数很好求 可以利用欧拉定理 即2的mod的欧拉函数-1次幂就是逆元。
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 2100000000
#define ldb long double
#define pb push_back
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE ll i=p;i<=n;++i)
#define go(x) for(ll i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE ll i=n;i>=p;--i)
#define pii pair<ll,ll>
#define mk make_pair
#define RE register
#define P 1000000007
#define F first
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define ull unsigned long long
#define ui unsigned
#define mod 111546435
#define l(x) t[x].l
#define r(x) t[x].r
#define sum(x) t[x].sum
#define tag(x) t[x].tag
#define d(x) t[x].d
#define zz p<<1
#define yy p<<1|1
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline ll read()
{
RE ll x=0,f=1;register char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const ll MAXN=200010;
ll n,Q,INV2,phi=36495360;
struct wy
{
ll l,r;
ll sum;
ll d,tag;
}t[MAXN<<2];
ll a[MAXN];
inline ll ksm(ll b,ll p)
{
ll cnt=1;
while(p)
{
if(p&1)cnt=cnt*b%mod;
b=b*b%mod;p=p>>1;
}
return cnt;
}
inline void build(ll p,ll l,ll r)
{
l(p)=l;r(p)=r;
if(l==r){sum(p)=a[l]%mod;return;}
ll mid=(l(p)+r(p))>>1;
build(zz,l,mid);build(yy,mid+1,r);
sum(p)=(sum(zz)+sum(yy))%mod;
}
inline void pushdown(ll p)
{
ll mid=(l(p)+r(p))>>1;
if(tag(p))
{
tag(zz)=(tag(zz)+tag(p))%mod;
tag(yy)=(tag(yy)+tag(p))%mod;
sum(yy)=(sum(yy)+(r(p)-mid)*tag(p))%mod;
sum(zz)=(sum(zz)+(mid-l(p)+1)*tag(p))%mod;
tag(p)=0;
}
if(d(p))
{
ll ww=mid-l(p)+1;
d(zz)=(d(zz)+d(p))%mod;
sum(zz)=(sum(zz)+(d(p)+d(p)*ww)%mod*ww%mod*INV2)%mod;
d(yy)=(d(yy)+d(p))%mod;
ww=r(p)-mid;
sum(yy)=(sum(yy)+(d(p)+d(p)*ww)%mod*ww%mod*INV2+d(p)*(mid-l(p)+1)%mod*(r(p)-mid)%mod)%mod;
tag(yy)=(tag(yy)+(mid-l(p)+1)*d(p))%mod;
d(p)=0;
}
}
inline void change(ll p,ll l,ll r,ll v)
{
if(l<=l(p)&&r>=r(p))
{
ll ww=r(p)-l(p)+1;
sum(p)=(sum(p)+ww*v)%mod;
tag(p)=(tag(p)+v)%mod;
return;
}
ll mid=(l(p)+r(p))>>1;
if(tag(p)||d(p))pushdown(p);
if(l<=mid)change(zz,l,r,v);
if(r>mid)change(yy,l,r,v);
sum(p)=(sum(zz)+sum(yy))%mod;
}
inline void modify(ll p,ll l,ll r,ll v,ll d)
{
if(l>r)return;
if(l<=l(p)&&r>=r(p))
{
ll ww=r(p)-l(p)+1;
sum(p)=(sum(p)+(d+d*ww)%mod*ww%mod*INV2%mod+v*ww%mod)%mod;
tag(p)=(tag(p)+v)%mod;
d(p)=(d(p)+d)%mod;
return;
}
if(tag(p)||d(p))pushdown(p);
ll mid=(l(p)+r(p))>>1;
if(r<=mid)modify(zz,l,r,v,d);
else
{
if(l>mid)modify(yy,l,r,v,d);
else
{
modify(zz,l,mid,v,d);
modify(yy,mid+1,r,(v+(mid-l+1)*d)%mod,d);
}
}
sum(p)=(sum(zz)+sum(yy))%mod;
}
inline ll ask(ll p,ll l,ll r)
{
if(l<=l(p)&&r>=r(p))return sum(p);
ll mid=(l(p)+r(p))>>1;
ll cnt=0;
if(tag(p)||d(p))pushdown(p);
if(l<=mid)cnt=(cnt+ask(zz,l,r))%mod;
if(r>mid)cnt=(cnt+ask(yy,l,r))%mod;
return cnt;
}
signed main()
{
//freopen("1.in","r",stdin);
get(n);INV2=ksm(2,phi-1);
//cout<<3*5*7*11*13*17*19*23<<endl;
//cout<<2*4*6*10*12*16*18*22<<endl;
//cout<<2*INV2%mod<<endl;
rep(1,n,i)get(a[i]);
build(1,1,n);
get(Q);
rep(1,Q,i)
{
ll op,l,r,m,d;
get(op);get(l);get(r);get(m);
if(op==1)get(d),change(1,l,r,m),modify(1,l+1,r,0,d);
else putl(ask(1,l,r)%m);
}
return 0;
}