小花梨的数组

Description

小花梨得到了一个长度为𝑛的数组𝑎,现在要对它进行三种操作:

⚫ 1 𝑙 𝑟 对所有的𝑖 ∈ [𝑙, 𝑟], 𝑎[𝑖] = 𝑎[𝑖] ∗ 𝑚𝑖𝑛𝑝𝑟𝑖𝑚𝑒(𝑎[𝑖])

⚫ 2 𝑙 𝑟 对所有的𝑖 ∈ [𝑙, 𝑟], 𝑎[𝑖] = 𝑎[𝑖] / 𝑚𝑖𝑛𝑝𝑟𝑖𝑚𝑒(𝑎[𝑖])

⚫ 3 𝑥 求𝑎[𝑥]的值 𝑚𝑖𝑛𝑝𝑟𝑖𝑚𝑒(𝑥) = { 1 (𝑥 = 1) 𝑥的最小素因子(𝑥 ≥ 2) 现在给出初始数组𝑎,对其进行𝑚次操作,对于第三种操作输出结果。

𝑚𝑖𝑛𝑝𝑟𝑖𝑚𝑒(𝑥) =  { 1 (𝑥 = 1) , 𝑥的最小素因子(𝑥 ≥ 2)}

现在给出初始数组𝑎,对其进行𝑚次操作,对于第三种操作输出结果。

Input

第一行输入两个正整数𝑛, 𝑚,表示数组的长度以及操作次数(1 ≤ 𝑛, 𝑚 ≤ 100000)

第二行输入𝑛个正整数表示数组𝑎(1 ≤ 𝑎𝑖 ≤ 1000000) 接下来𝑚行表示𝑚次操作,每行输入格式为"1 𝑙 𝑟"或者"2 𝑙 𝑟",或者"3 𝑥",对应上述三种操作1 ≤ 𝑙, 𝑟, 𝑥 ≤ 𝑛, 𝑙 ≤ r

Output

对于第三种操作输出答案即可,答案对10 9 + 7进行取模。

Sample Input

5 8

1 2 3 4 5

1 2 4

3 2

3 3

2 2 5 

3 2

3 5

1 5 5

3 5

Sample Output

4

9

2

1

1

解题思路:用线段树+lazy标志去维护每个点操作了多少次,乘的时候tag值加1,除的时候tag值-1。当tag值为-1的时候更新这个点。

#include <bits/stdc++.h>
using namespace std;
#define N 100005
#define ll long long
vector<int>vec[100005];
int c[100005],d[100005];
struct node
{
   int l,r,w,f,tag;
}tree[4*N+5];
ll aaa,bbb;
const ll mod=1e9+7;
ll quick(ll n,ll m)
{
    ll ans=1;
    ll c=mod;
    n=n%c;
    while(m>0)
    {
        if(m&1) ans=(ans*n)%c;
        n=(n*n)%c;
        m>>=1;
    }
    return ans;
}
void build(int k,int l,int r)
{
    tree[k].l=l,tree[k].r=r;
    if(l==r)
    {
        scanf("%d",&tree[k].w);
        c[l]=tree[k].w;
        return;
    }
    int mid=(l+r)>>1;
    build(k*2,l,mid);
    build(k*2+1,mid+1,r);
}
void down(int k)
{
    tree[2*k].tag+=tree[k].tag;
    tree[2*k+1].tag+=tree[k].tag;
    tree[k].tag=0;
}//下传标记 
void min_prime(int pos,int k)
{
    int i=2;
    while(i*i<=k)
    {
        if(k%i==0)
        {
            while(k%i==0)
            {
                k=k/i;
                vec[pos].push_back(i);
            }
        }
        i++;
    }
    if(k>1) vec[pos].push_back(k);
}
void change(int k)
{
    if(tree[k].l==tree[k].r)
    {
        tree[k].tag=0;
        if(tree[k].w!=1) 
        {
            int m_prime=vec[tree[k].l][d[tree[k].l]];
            d[tree[k].l]++;
            tree[k].w=tree[k].w/m_prime;
            if(tree[k].w==1) tree[k].tag=10000;
        }
        return;
    }
    if(tree[k].tag==-1) down(k);
    if(tree[2*k].tag==-1) change(2*k);
    if(tree[2*k+1].tag==-1) change(2*k+1);
}
void change_interval(int k,int l,int r,int c)
{
    if(tree[k].l>=l&&tree[k].r<=r)
    {
        tree[k].tag+=c; 
        if(tree[k].tag==-1) change(k);
        return; 
    }
    if(tree[k].tag) down(k);
    int m=(tree[k].l+tree[k].r)/2;
    if(l<=m) change_interval(k*2,l,r,c);
    if(r>m) change_interval(k*2+1,l,r,c);
    
}
void ask_point(int k,int x)
{
    if(tree[k].l==tree[k].r)
    {
        aaa=tree[k].w;
        bbb=tree[k].tag;
        return ;
    }
    if(tree[k].tag) down(k);
    int m=(tree[k].l+tree[k].r)/2;
    if(x<=m) ask_point(k*2,x);
    else ask_point(k*2+1,x);
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i=1;i<=n;i++) min_prime(i,c[i]);
    while(m--)
    {
        int p,a,b;
        scanf("%d",&p);
        if(p==1)
        {
            scanf("%d%d",&a,&b);
            change_interval(1,a,b,1);
        }
        else if(p==2)
        {
            scanf("%d%d",&a,&b);
            change_interval(1,a,b,-1);
        }
        else 
        {
            int kk;
            scanf("%d",&kk);
            ask_point(1,kk);
            if(aaa==1) cout<<"1\n";
            else
            {
                int m_prime=vec[kk][d[kk]];
                ll sum=aaa*quick(m_prime,bbb)%mod;
                cout<<sum<<endl;    
            }
            
        }
    }
} 

 

posted @ 2019-05-19 22:42  Dorom  阅读(260)  评论(0)    收藏  举报