您的位置:首页 > 其它

BZOJ 4026 dC Loves Number Theory 分块+十字链表/可持久化线段树

2015-04-30 16:19 393 查看
题目大意:给定一个序列,多次询问某段区间乘积的φ\varphi值对10007771000777的模

我竟然卡过去了233333

将序列分块,记录fi,jf_{i,j}表示第ii块左端点到第jj个点中出现的所有质数pp的p−1p\frac{p-1}p之积

每次询问[x,y][x,y],首先取出[x,y][x,y]区间内所有数的积,然后乘上fst,yf_{st,y}(其中stst是xx后面第一个块端点所在块)

现在还剩[x,l[st]][x,l[st]]部分没有统计

由于10610^6以内的数分解得到的不同的质因数最多只有77个,因此暴力枚举零碎部分的质数即可

现在对于每个质数我们需要判断是否出现过

我们只需要判断这个质数下一次出现的位置是否大于yy即可

用十字链表搞一搞就可以了

时间复杂度O(7mn√)O(7m\sqrt n)

这当然不是正解- -

珍爱生命,远离卡常,我们来看正解吧

实际上我们要统计的就是[x,y][x,y]区间内所有出现过的质数pp的p−1p\frac{p-1}p之积

我们想到了什么?没错,HH的项链!

由于强制在线,因此我们用可持久化线段树搞一搞就行了。时间复杂度O(mlogn)O(m\log n)

[code]#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 50500
#define B 700
#define MOD 1000777
using namespace std;
struct abcd{
    abcd *up,*rt;
    int p,belong;
    void* operator new (size_t)
    {
        static abcd mempool[M*7],*C=mempool;
        return C++;
    }
}*head[M],*last[80800];
int n,m,b,last_ans;
int a[M];
int prime[80800],tot;
long long inv[MOD];
int l[M],belong[M];
int prod[B][M];
void Linear_Shaker()
{
    static bool not_prime[1001001];
    int i,j;
    for(i=2;i<=1000000;i++)
    {
        if(!not_prime[i])
            prime[++tot]=i;
        for(j=1;prime[j]*i<=1000000;j++)
        {
            not_prime[prime[j]*i]=true;
            if(i%prime[j]==0)
                break;
        }
    }
    for(inv[1]=1,i=2;i<MOD;i++)
        inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
}
abcd* Decomposition(int pos)
{
    int i,n=a[pos];
    abcd *re=0x0;
    for(i=1;prime[i]*prime[i]<=n;i++)
        if(n%prime[i]==0)
        {
            abcd *temp=new abcd;
            temp->up=re;
            temp->p=i;
            temp->belong=pos;
            if(last[i])
                last[i]->rt=temp;
            re=last[i]=temp;

            while(n%prime[i]==0)
                n/=prime[i];
        }
    if(n!=1)
    {
        i=lower_bound(prime+1,prime+tot+1,n)-prime;

        abcd *temp=new abcd;
        temp->up=re;
        temp->p=i;
        temp->belong=pos;
        if(last[i])
            last[i]->rt=temp;
        re=last[i]=temp;
    }
    return re;
}
int Query(int x,int y)
{
    int i,st=belong[x-1]+1,re=inv[a[x-1]]*a[y]%MOD;
    abcd *temp;
    if(y>=l[st])
        re=(long long)re*prod[st][y]%MOD;
    for(i=min(y,l[st]-1);i>=x;i--)
        for(temp=head[i];temp;temp=temp->up)
            if(!temp->rt||temp->rt->belong>y)
                re=re*inv[prime[temp->p]]%MOD*(prime[temp->p]-1)%MOD;
    return re;
}
namespace IStream{  
    const int L=1<<15;  
    char buffer[L],*S,*T;  
    inline char Get_Char()  
    {  
        if(S==T)  
        {  
            T=(S=buffer)+fread(buffer,1,L,stdin);  
            if(S==T) return EOF;  
        }  
        return *S++;  
    }  
    inline int Get_Int()  
    {  
        char c;  
        int re=0;  
        for(c=Get_Char();c<'0'||c>'9';c=Get_Char());  
        while(c>='0'&&c<='9')  
            re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char();  
        return re;  
    }  
}
int main()
{
    using namespace IStream;
    int i,j,x,y;
    abcd *temp;
    cin>>n>>m;
    b=200;
    Linear_Shaker();
    for(i=1;i<=n;i++)
    {
        a[i]=Get_Int();
        head[i]=Decomposition(i);
    }
    for(a[0]=1,i=1;i<=n;i++)
        a[i]=(long long)a[i]*a[i-1]%MOD;
    for(i=1;i<=n;i++)
        belong[i]=(i-1)/b+1;
    for(i=1;i<=belong
;i++)
        l[i]=(i-1)*b+1;
    l[i]=0x3f3f3f3f;

    static int v[80800],ans;
    for(j=1;j<=belong
;j++)
    {
        ans=1;
        for(i=l[j];i<=n;i++)
        {
            for(temp=head[i];temp;temp=temp->up)
                if(v[temp->p]!=j)
                {
                    v[temp->p]=j;
                    ans = ans * inv[prime[temp->p]] % MOD * (prime[temp->p]-1) % MOD ;
                }
            prod[j][i]=ans;
        }
    }

    for(i=1;i<=m;i++)
    {
        x=Get_Int();
        y=Get_Int();
        x^=last_ans;
        y^=last_ans;
        printf("%d\n",last_ans=Query(x,y));
    }
    //puts("Fuck♂You!");
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: