• BZOJ4026: dC Loves Number Theory


    Description

     dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯
    竭的水题资源。 
      给定一个长度为 n的正整数序列A,有q次询问,每次询问一段区间内所有元素乘积的
    φ(φ(n)代表1~n 中与n互质的数的个数) 。由于答案可能很大,所以请对答案 mod 10^6 + 
    777。 (本题强制在线,所有询问操作的l,r都需要 xor上一次询问的答案 lastans,初始时,
    lastans = 0) 

    Input

     第一行,两个正整数,N,Q,表示序列的长度和询问的个数。 

    第二行有N 个正整数,第i个表示Ai. 
    下面Q行,每行两个正整数,l r,表示询问[l ^ lastans,r ^ lastans]内所有元素乘积的φ 

    Output

    Q行,对于每个询问输出一个整数。 

    Sample Input

    5 10
    3 7 10 10 5
    3 4
    42 44
    241 242
    14 9
    1201 1201
    0 6
    245 245
    7 7
    6 1
    1203 1203

    Sample Output

    40
    240
    12
    1200
    2
    240
    4
    4
    1200
    4

    HINT

    1 <= N <= 50000 

    1 <= Q <= 100000 

    1 <= Ai <= 10^6 
     
     
    考虑phi函数的定义
    phi(n)=n*∏(pi-1)/pi。
    所以我们对于每个询问,计算出询问区间内有多少不同的素数就行啦。
    这难道不是一个经典问题吗?在线回答区间不同数的个数。
    设f[i]表示第i个素数上一次出现的位置,那么我们用函数式线段树计算一下区间内f[i]<L-1的数的(pi-1)/pi之积即可。
    一个正整数最多有logn个质因子,而每插入一个质因子是logn的,所以时间复杂度为O(nlog^2n)-O(logn)。
    另外掌握了O(n)求1到n逆元的姿势。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int maxn=50010;
    const int mod=1000777;
    const int maxnode=5000010;
    int n,m,cnt,A[maxn],vis[mod+5],first[mod+5],pri[mod],next[mod*3],to[mod*3],e;
    ll inv[mod+5],S[maxn],sumv[maxnode],lastans;
    void init() {
        inv[1]=inv[0]=1;
        rep(i,2,mod) inv[i]=((mod-mod/i)*inv[mod%i]+mod)%mod;
        rep(i,2,1000000) if(!vis[i]) {
            pri[++cnt]=i;
            for(int j=i;j<=1000000;j+=i) {
                vis[j]=1;
                to[++e]=cnt;next[e]=first[j];first[j]=e;
            }
        }
    }
    int root[maxn],last[mod+5],ls[maxnode],rs[maxnode],ToT;
    void update(int& y,int x,int l,int r,int p,ll v) {
        sumv[y=++ToT]=((x?sumv[x]:1)*v)%mod;if(l==r) return;
        int mid=l+r>>1;ls[y]=ls[x];rs[y]=rs[x];
        if(p<=mid) update(ls[y],ls[x],l,mid,p,v);
        else update(rs[y],rs[x],mid+1,r,p,v);
    }
    ll query(int y,int l,int r,int pos) {
        if(l==r) return y?sumv[y]:1;
        int mid=l+r>>1;
        if(pos<=mid) return query(ls[y],l,mid,pos);
        return ((ls[y]?sumv[ls[y]]:1)*query(rs[y],mid+1,r,pos))%mod;
    }
    int main() {
        init();S[0]=1;
        n=read();m=read();
        rep(i,1,n) A[i]=read(),S[i]=(S[i-1]*A[i])%mod;
        rep(x,1,n) {
            root[x]=root[x-1];
            for(int i=first[A[x]];i;i=next[i]) update(root[x],root[x],0,n,last[to[i]],(pri[to[i]]-1)*inv[pri[to[i]]]%mod),last[to[i]]=x;
        }
        while(m--) {
            int l=read()^lastans,r=read()^lastans;
            lastans=(S[r]*inv[S[l-1]])%mod;
            (lastans*=inv[query(root[l-1],0,n,l-1)]*query(root[r],0,n,l-1))%=mod;
            printf("%lld
    ",lastans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    JavaScript入门基础(三)
    JavaScript入门基础(二)
    Web页面该如何布局
    如何通过SQL创建删除表的索引,UNIQUE KEY
    vim使用大全
    安装vmwaretools后 真机和虚拟机仍不能复制黏贴
    php通用函数html时间文件大小生成随机数
    Centos下安装配置phpmyadmin
    [Leetcode 43] 11 Container With Most Water
    [Leetcode 39] 129 Sum Root to Leaf Numbers
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5250989.html
Copyright © 2020-2023  润新知