本题的空间限制是32MB
可以发现实际上就是要求有多少对线段产生了相交
又因为y轴上是升序,所以就是求产生的序列中,有多少个逆序对
可以发现因为数据生成的方法是有迹可循的,我们可以将值域分块
每a的长度就是一个块,可以通过一个块的贡献统计其他块的贡献,就减少了空间和时间复杂度
用树状数组来维护这个东西
#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define RG register
using namespace std;
int shu,n,a,mod,maxa,piece,pos,pd[100005];
long long all,now,another;
long long ans,tree[100005];
inline void modify(int x)
{
x++;
for(RG int i=x;i<=1e5;i+=(i&-i))
tree[i]++;
}
inline long long query(int x)
{
x++;
RG long long ans=0;
for(RG int i=x;i>=1;i-=(i&-i))
ans+=tree[i];
return ans;
}
int get(int x)
{
return x/a+1;
}
inline int moc(int x)
{
if(x>=mod) return x-mod;
return x;
}
int main()
{
freopen("fly.in","r",stdin);
freopen("fly.out","w",stdout);
cin>>n>>shu>>a>>mod;
int pre=shu;
modify(shu%a);
int pos=get(shu)-1,remain=1,tot=1;
for(int i=2;i<=n;i++)
{
shu+=a;
if(shu>=mod)
{
shu-=mod;
tot++;
modify(shu);
remain=query(shu);
}
int now=get(shu);
int temp=tot*(now-1)+remain;
if(shu%a>=pre%a) temp-=min(now,pos);
else temp-=min(now-1,pos);
ans+=i-temp;
}
cout<<ans;
return 0;
}