模拟 飞(fly)
问题 C: 飞(fly)
时间限制: 1 Sec 内存限制: 32 MB
题目描述
liu_runda决定提高一下知识水平,于是他去请教郭神.郭神随手就给了liu_runda一道神题,liu_runda并不会做,于是把这个题扔到联考里给高二的做.
郭神有n条位于第一象限内的线段,给出每条线段与x轴和y轴交点的坐标,显然这样就可以唯一确定每一条线段.
n条线段和y轴交点的纵坐标分别为1,2,3,4…n.我们记和y轴交点纵坐标为i的线段和x轴交点的横坐标为x[i]+1,x[i]按这样的方式生成:
x[1]由输入给出.
x[i]=(x[i-1]+a) % mod,2<=i<=n.
即:如果x[3]=4,则与y轴交点纵坐标为3的抛物线,和x轴交点的横坐标为4+1=5.
我们保证给出的n,x[1],a,mod使得所有的x[i]互不相同.
对于第一象限内的所有点(点的横纵坐标可以是任意实数),如果一个点被x条线段经过,它的鬼畜值就是x*(x-1)/2.
求第一象限内的所有点的鬼畜值之和.
【输入格式】
一行4个整数n,x[1],a,mod
【输出格式】
1行一个整数表示鬼畜值之和.
【样例输入1】(即sample1.in)
5 2 4 7
【样例输出1】(即sample1.ans)
5
【数据范围】
第1,2个测试点,n<=100.
第3,4个测试点,n<=10^5.
第5,6个测试点的数据,a<=10.
第7,8个测试点,x[1]=a.
第9,10个测试点,无特殊限制.
对于全部数据,1<=n<=1e7,1<=a<=1e5,1<=mod<=1e8,a,mod互质,n< mod,给出的n,x[1],a,mod使得所有的x[i]互不相同.
请选手注意,1e7个int类型的变量将占用大约40mb的内存,导致内存超限,本题得0分.
会发现这是个等差数列。对于每一段n*a~(n+1)*a(我把它称为一个区间)里,每一轮(也就是从第一个
#pragma GCC optimize("O3")
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int read()
{
int sum=0,f=1;char x=getchar();
while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}
return sum*f;
}
int n,x,a,mod;
int t[100050];
ll ans;
int lowbit(int x){return x&(-x);}
int q(int x){int s=0;while(x>0){s+=t[x];x-=lowbit(x);}return s;}
void add(int x){while(x<=a)t[x]++,x+=lowbit(x);}
int main()
{
n=read();x=read();a=read();mod=read();
int i=1,st=x,cnt=1,sum=0,num=0,hh;
for(i=2;i<=n;i++){x+=a;if(x>=mod)break;}
for(;i<=n;i++)
{
if(x>=mod){x-=mod;cnt=1,sum=q(x+1),add(x+1);num++;}
hh=(x>st?(x-st)/a+1:0)+sum+(cnt-1)*num;
//cout<<x<<" "<<hh<<endl;
ans+=i-1-hh;x+=a;cnt++;
}
cout<<ans;
}