20181030NOIP模拟赛T3

2017种树

2017共有N棵树从0到N-1标号。现要把这些树种在一条直线上,第i棵树的种植位置X[i]如下确定:

X[0] = X[0] MOD L;

X[i] = (X[i-1]*A+B) MOD L。

每棵树种植的费用,是所有标号比它小的树与它的距离之和。2017请你计算各棵树的费用之积,最后对1000000007取余。

输入:

共五行:

第一行为N

第二行为L

第三行为X[0]

第四行为A

第五行为B

输出:

总费用

Input1:

5

10

3

1

1

Output1:

180

样例解释:

5棵树的位置分别为: 3, 4, 5, 6, 7.

费用分别为: 1, 3, 6, 10. (从第一棵树开始)

总费用为: 1 × 3 × 6 × 10 = 180.

数据范围:

10%的数据:N<=10;

60%的数据:N<=5×10^4;

100%的数据:N,L<=200000;  X[0] ,A, B<=10^9.

思路:

权值线段树好题

一个点和他前面某个点的距离

等于这个点坐标减去前面那个点的坐标

那么,前面所有点到这个点的距离和

等于前面这些点的数量*当前点坐标-前面点的坐标和

对于这个问题,我们开一颗权值线段树维护即可

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rs 262143
#define p 1000000007 
#define rii register int i
#define rij register int j
#define int long long
using namespace std;
long long n,l1,y[200005],a,b,ans;
struct tree{
    long long cnt,sum;
}x[rs*5];
void add(int wz,int l,int r,int bh)
{
    if(wz==l&&wz==r)
    {
        x[bh].cnt++;
        x[bh].sum+=wz;
        return;
    }
    int mid=(l+r)/2;
    if(wz<=mid)
    {
        add(wz,l,mid,bh*2);
    }
    else
    {
        add(wz,mid+1,r,bh*2+1);
    }
    x[bh].cnt=x[bh*2].cnt+x[bh*2+1].cnt;
    x[bh].sum=x[bh*2].sum+x[bh*2+1].sum;
}
tree query(int l,int r,int nl,int nr,int bh)
{
    if(l<nl)
    {
        l=nl;
    }
    if(r>nr)
    {
        r=nr;
    }
    if(nl==l&&nr==r)
    {
        return x[bh];
    }
    int mid=(nl+nr)/2;
    tree kkk;
    tree lzn;
    lzn.cnt=0,lzn.sum=0,kkk.sum=0,kkk.cnt=0;
    if(l<=mid)
    {
        kkk=query(l,r,nl,mid,bh*2);
    }
    if(r>mid)
    {
        lzn=query(l,r,mid+1,nr,bh*2+1);
    }
    kkk.cnt+=lzn.cnt;
    kkk.sum+=lzn.sum;
    return kkk;
}
signed main()
{
    freopen("gg.in","r",stdin);
    freopen("gg.out","w",stdout);
    scanf("%lld%lld%lld%lld%lld",&n,&l1,&y[0],&a,&b);
    y[0]%=l1;
    add(y[0],0,rs,1);
    ans=1;
    for(int i=1;i<=n-1;i++)
    {
        long long an=0;
        y[i]=(y[i-1]*a+b)%l1;
        tree kkk;
        kkk=query(0,y[i],0,rs,1);
        an+=kkk.cnt*y[i];
        an%=p;
        an-=kkk.sum;
        an+=p;
        an%=p;
        kkk=query(y[i],l1-1,0,rs,1);
        an+=kkk.sum;
        an-=kkk.cnt*y[i];
        an+=p;
        an%=p;
        ans*=an;
        ans%=p;
        add(y[i],0,rs,1);
    }
    printf("%lld\n",ans);
}

猜你喜欢

转载自www.cnblogs.com/ztz11/p/9877780.html