BZOJ 3813 odd countries

Number Theory segment tree +

After reading such a long list of topics, now extract useful information

First $ number * x + product * y = 1 $ this condition

If you want $ x $, $ y $ solvable, and then $ $ $ Product Number must satisfy $ $ \ gcd (number, product) = 1 $

Then the query operation into the obtained $ [1, product] $ how much the number of prime $ $ Product

Then this is seeking $ \ varphi (product) $

Because the term formula Euler function $ \ varphi (x) = x \ prod_ {i = 1} ^ {k} (1- \ frac {1} {p_ {i}}) $, p is a prime factor of x

Observation subject, the subject to ensure that all the money is obtained from the first 60 prime numbers multiplied

So long as the $ product $ determined by inverse able to find out the answer, 19,961,993 are prime numbers, then you can Fermat's Little Theorem

Because the operation is seeking $ product $ interval, so as to maintain the number of deposit money banks with each segment tree

The segment tree to record the product range and the current prime interval appears

Because only 60 prime can be pressed to form a long long save

So when the pushup is also convenient, directly to the left and right son of the son of state or operation can be

So the next question is a single point of modification segment tree, ask the interval obtained a $ product $

Finally, note that when the open long long, constant also turn into a Long Long (check this check for an hour)

#include <bits/stdc++.h>
#define mod (long long)19961993
using namespace std;
const long long MAXN=100100;
long long n,p[61],w,in[61];
struct node
{
    long long l,r;
    long long mask,mul;
}sh[MAXN*4];
bool check(long long x)//判断质数
{
    for (long long i=2;i*i<=x;i++)
    {
        if (x%i==0)
          return false;
    }
    return true;
}
long long split(long long x)//质因数分解
{
    long long m=0;
    for (long long i=0;i<w;i++)
    {
        if (x%p[i]==0)
          m|=(1ll<<i);//注意
    }
    return m;
}
long longm_pow ( Long  Long A, Long  Long B) 
{ 
    Long  Long ANS = . 1 ;
     the while (B> 0 ) 
    { 
        IF (B & . 1 ) 
          ANS = (ANS * A)% MOD; 
        A = (A * A)% MOD; 
        B = >> . 1 ; 
    } 
    return ANS% MOD; 
} 
Long  Long INV ( Long  Long X) // by Fermat's little theorem to obtain inverse 
{ 
    return m_pow (X, mod- 2 )%mod;
}
void pushup(long long x)
{
    sh[x].mul=(sh[x+x].mul*sh[x+x+1].mul)%mod;
    sh[x].mask=sh[x+x].mask|sh[x+x+1].mask;
}
void build(long long x,long long ll,long long rr)
{
    sh[x].l=ll;
    sh[x].r=rr;
    if (ll==rr)
    {
        sh[x].mul=(long long)3;//注意
        sh[x].mask=split((long long)3);
        return;
    }
    long long mid;
    mid=(ll+rr)>>1;
    build(x+x,ll,mid);
    build(x+x+1,mid+1,rr);
    pushup(x);
}
void change(long long x,long long wh,long long v)//线段树单点修改
{
    if (sh[x].l==wh && sh[x].r==wh)
    {
        sh[x].mul=v;
        sh[x].mask=split(v);
        return;
    }
    long long mid;
    mid=(sh[x].l+sh[x].r)>>1;
    if (wh<=mid)
      change(x+x,wh,v);
    else
      change(x+x+1,wh,v);
    pushup(x);
}
long long query1(long long x,long long ll,long long rr)//查找乘积
{
    if (sh[x].l>=ll && sh[x].r<=rr)
      return sh[x].mul;
    long long mid;
    long long ans=1;
    mid=(sh[x].l+sh[x].r)>>1;
    if (ll<=mid)
      ans=(ans*query1(x+x,ll,rr))%mod;
    if (rr>mid)
      ans=(ans*query1(x+x+1,ll,rr))%mod;
    pushup(x);
    return ans;
}
long long query2(long long x,long long ll,long long rr)//查找区间质数出现情况
{
    if (sh[x].l>=ll && sh[x].r<=rr)
      return sh[x].mask;
    long long mid;
    long long ma=0;
    mid=(sh[x].l+sh[x].r)>>1;
    if (ll<=mid)
      ma=ma|query2(x+x,ll,rr);
    if (rr>mid)
      ma=ma|query2(x+x+1,ll,rr);
    pushup(x);
    return ma;
}
int main()
{
    scanf("% LLD", & N-);
     for ( Long  Long I = 2 ; I <= 281 is ; I ++ ) 
    { 
        IF (Check (I)) 
        { 
            P [W] = I; // preprocessing the first 60 prime 
            W ++ ; 
        } 
    } 
    for ( int I = 0 ; I <W; I ++ )
       in [I] = INV (P [I]); // and inverse 
    Build ( . 1 , . 1 , 100000 );
     the while (N-- ) 
    { 
        Long  Long a,b,c;
        scanf("%lld%lld%lld",&a,&b,&c);
        if (a==0)
        {
            long long pro,m;
            long long tot=1;
            pro=query1(1,b,c);
            m=query2(1,b,c);
            for (long long i=0;i<w;i++)
            {
                if ((m>>i)&1)
                  tot=(tot*(p[i]-. 1 ) MOD%) * in [I]% MOD; // Euler function term formulas 
            } 
            the printf ( " % LLD \ n- " , (Pro * TOT)% MOD); 
        } 
        the else 
        { 
            Change ( . 1 , B, C ); 
        } 
    } 
}

 

Guess you like

Origin www.cnblogs.com/huangchenyan/p/11279111.html