zoukankan      html  css  js  c++  java
  • jzoj100045. 好数

    Description

    我们定义一个非负整数是“好数”,当且仅当它符合以下条件之一:
    1.这个数是0或1
    2.所有小于这个数且与它互质的正整数可以排成一个等差数列例如,8就是一个好数,因为1,3,5,7排成了等差数列。
    给出N个非负整数,然后进行如下三个操作:
    1.询问区间[L,R]有多少个好数
    2.将区间[L,R]内所有数对S取余(S≤1000000)
    3.将第C个数更改为X

    Input

    第一行包含两个正整数N和M,M表示操作数目
    第二行包含N个非负整数。
    接下来的M行每行表示1个操作:“1 L R”表示第1个操作,“2 L R S”表示第2个操作,“3 C X”表示第3个操作。

    Output

    对每个操作1,输出一个非负整数,表示区间内好数的个数。

    Sample Input

    Sample1:
    3 6
    4 6 9
    1 1 3
    1 3 3
    2 1 1 10
    1 1 3
    3 2 4
    1 1 3
    Sample2:
    8 5
    12 24 17 31 16 21 18 30
    1 2 5
    2 4 7 7
    3 2 13
    1 1 8
    1 3 6

    Sample Output

    Sample1:
    2
    0
    2
    2
    Sample2:
    3
    6
    4

    Data Constraint

    0<=n,m<=105,n<=1060<=n,m<=10^5,n个数大小<=10^6

    题解

    这题很巧妙。
    首先我们要确定好数是那几个。
    那么打表找规律
    发现好数必须是质数、2的次幂或者6。
    证明:
    如果一个数为2的次幂,那么显然这个成立。
    如果一个数为质数,这也是可以肯定正确的。
    如果一个数不为质数且不是2的次幂。
    那么就可以设这个数为x2kx*2^k
    当k不为0时。
    可以发现,x为奇数。
    那么,就可以知道x2x-2x+2x+2必定与x2kx*2^k互质。
    而且,根据常识,x2k1x*2^k-111也是与x2kx*2^k互质的。
    由于x-2和x+2靠的最近,而且中间的任何数都是与x2kx*2^k不互质的。
    那么就可以确定了,从1开始每4个为一个互质的数。
    那么,若有一个数与任意的1+4y1+4*y互质但与其他任何数都不互质,这个数就是好数。
    列举一下可以发现,这个数如果大于等于了9,这个数就要即与9互质又与3不互质,不成立。
    然而小于9时,只有一个6满足。

    当k为0时。
    显然上述条件不成立。
    但是,显然的,x1x-1x2x-2xx三个互质。
    那么意味着,每个互质的数要连续。
    然而比这个x小的数中,必然有个与它不互质。
    那么这种情况就没有好数。

    至此,证明完成。

    接下来,我们知道了什么数字为好数,什么数字不为好数。
    我们就可以快速判断了。

    假设我们可以建一颗线段树,里面储存每个位置好数个数的情况。
    如果一个位置为好数,线段树相应位置为1,反之为0。
    这样可以快速解决1、3操作。
    对于2操作,我们要对树取模操作。
    这个显然有点棘手。
    但是我们发现,一个数不改变的情况下,对任意一个数取模,要么不变,要么最大变成原来的一半。
    那么就可以发现,一个数字最多被模log下。
    至此,想到了什么?暴力!
    记得之前有一个小技巧,就是线段树中维护最大的数字,如果某个区间最大数字超过模数,证明这个区间需要取模。
    那么递归下去暴力修改即可。
    理论最坏时间复杂度O(mlog2106)O(m*log^210^6)
    实际远小于这个复杂度。

    代码

    uses math;
    var
            i,j,k,l,n,m,tot,ans:longint;
            gos,bz:array[0..2000000] of boolean;
            zs:array[2..2000000] of boolean;
            tree:array[1..4000000] of longint;
            zd:array[1..4000000] of longint;
            a,b:array[1..1000000] of longint;
            kind,x,y,z:array[1..1000000] of longint;
            qj:boolean;
    procedure maketree(x,l,r:longint);
    begin
            if l=r then
            begin
                    tree[x]:=b[l];
                    zd[x]:=a[l];
            end
            else
            begin
                    maketree(x+x,l,(l+r)shr 1);
                    maketree(x+x+1,(l+r)shr 1+1,r);
                    tree[x]:=tree[x*2]+tree[x*2+1];
                    zd[x]:=max(zd[x*2],zd[x*2+1]);
             end;
    end;
    procedure insert(x,l,r,st,value:longint);
    var
            m,k:longint;
    begin
            if (l=r) then
            begin
                    if gos[value] then k:=1
                    else k:=0;
                    tree[x]:=k;
                    zd[x]:=value;
            end
            else
            begin
                    m:=(l+r)shr 1;
                    if st<=m then insert(2*x,l,m,st,value)
                    else insert(2*x+1,m+1,r,st,value);
                    tree[x]:=tree[x*2]+tree[x*2+1];
                    zd[x]:=max(zd[x*2],zd[x*2+1]);
            end;
    end;
    procedure gg(x,l,r,mo:longint);
    var
            m:longint;
    begin
            if (l=r) then
            begin
                    zd[x]:=zd[x] mod mo;
                    if gos[zd[x]] then
                    tree[x]:=1
                    else
                    tree[x]:=0;
            end
            else
            begin
                    m:=(l+r)shr 1;
                    if (zd[x*2]>=mo) then gg(2*x,l,m,mo);
                    if (zd[x*2+1]>=mo) then gg(2*x+1,m+1,r,mo);
                    tree[x]:=tree[x*2]+tree[x*2+1];
                    zd[x]:=max(zd[x*2],zd[x*2+1]);
            end;
    
    end;
    procedure change(x,l,r,st,en,mo:longint);
    var
            m:longint;
    begin
            if (l=st) and (r=en) then
            begin
                    if zd[x]>=mo then
                    begin
                            gg(x,l,r,mo);
                    end;
            end
            else
            begin
                    m:=(l+r)shr 1;
                    if en<=m then change(2*x,l,m,st,en,mo)
                    else if st>m then change(2*x+1,m+1,r,st,en,mo)
                    else
                    begin
                            change(2*x,l,m,st,m,mo);
                            change(2*x+1,m+1,r,m+1,en,mo);
                    end;
                    tree[x]:=tree[x*2]+tree[x*2+1];
                    zd[x]:=max(zd[x*2],zd[x*2+1]);
            end;
    end;
    procedure look_for(x,l,r,st,en:longint);
    var
            m:longint;
    begin
            if (l=st)and(r=en) then
            begin
                    inc(ans,tree[x]);
            end
            else
            begin
                    m:=(l+r)shr 1;
                    if en<=m then look_for(2*x,l,m,st,en)
                    else if st>m then look_for(2*x+1,m+1,r,st,en)
                    else
                    begin
                            look_for(2*x,l,m,st,m);
                            look_for(2*x+1,m+1,r,m+1,en);
                    end;
            end;
    end;
    begin
            fillchar(bz,sizeof(bz),true);
            for i:=2 to 1000000 do
            begin
                    if bz[i] then
                    for j:=2 to 1000000 div i do bz[i*j]:=false;
            end;
            l:=1;
            for i:=1 to 30 do
            begin
                    l:=l*2;
                    if l<1000000 then bz[l]:=true else break;
            end;
            bz[6]:=true;
            gos:=bz;
    
            readln(n,m);
            for i:=1 to n do
            begin
                    read(a[i]);
                    if gos[a[i]] then
                    begin
                            b[i]:=1;
                    end;
            end;
            maketree(1,1,n);
            for i:=1 to m do
            begin
                    read(kind[i]);
                    if kind[i]=2 then
                    begin
                            qj:=true;
                            readln(x[i],y[i],z[i]);
                    end;
                    if kind[i]=1 then
                    begin
                            readln(x[i],y[i]);
                    end;
                    if kind[i]=3 then
                    begin
                            readln(x[i],z[i]);
                    end;
            end;
            for i:=1 to m do
            begin
                    if kind[i]=1 then
                    begin
                            ans:=0;
                            look_for(1,1,n,x[i],y[i]);
                            writeln(ans);
                    end
                    else
                    if kind[i]=2 then
                    begin
                            change(1,1,n,x[i],y[i],z[i]);
                    end
                    else
                    if kind[i]=3 then
                    begin
                            insert(1,1,n,x[i],z[i]);
                    end;
            end;
    end.
    
    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    js中的面向对象
    js 定时器
    js中 关于DOM的事件操作
    js 函数
    js流程控制;常用内置对象
    js数据类型基础
    js基础语法
    js初识
    css 选择器;盒模型
    软件系统建模之用例视图
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148379.html
Copyright © 2011-2022 走看看