Codeforces-1114F:Please, another Queries on Array?(线段树)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/87109771

F. Please, another Queries on Array?
time limit per test 5.5 seconds
memory limit per test 256 megabytes
input standard input
output standard output
You are given an array a 1 , a 2 , , a n . a_1,a_2,…,a_n.

You need to perform q queries of the following two types:

“MULTIPLY l r x” — for every i ( l i r ) i (l≤i≤r) multiply a i a_i by x.
“TOTIENT l r” — print φ ( i = l r a i ) φ(∏_{i=l}^{r}a_i) taken modulo 1 0 9 + 7 10^9+7 , where φ φ denotes Euler’s totient function.
The Euler’s totient function of a positive integer n (denoted as φ ( n ) φ(n) ) is the number of integers x ( 1 x n ) x (1≤x≤n) such that g c d ( n , x ) = 1. gcd(n,x)=1.

Input
The first line contains two integers n and q ( 1 n 4 1 0 5 , 1 q 2 1 0 5 ) (1≤n≤4⋅10^5, 1≤q≤2⋅10^5) — the number of elements in array a and the number of queries.

The second line contains n integers a 1 , a 2 , , a n ( 1 a i 300 ) a_1,a_2,…,a_n (1≤a_i≤300) — the elements of array a.

Then q lines follow, describing queries in the format given in the statement.

“MULTIPLY l r x” ( 1 l r n , 1 x 300 ) (1≤l≤r≤n, 1≤x≤300) — denotes a multiplication query.
“TOTIENT l r” ( 1 l r n ) (1≤l≤r≤n) — denotes a query on the value of Euler’s totient function.
It is guaranteed that there is at least one “TOTIENT” query.

Output
For each “TOTIENT” query, print the answer to it.

Example
input
4 4
5 9 1 2
TOTIENT 3 3
TOTIENT 3 4
MULTIPLY 4 4 3
TOTIENT 4 4
output
1
1
2

思路:题意很清楚。根据欧拉定理的公式,只要记录区间内数的乘积以及出现了哪些质数即可。

因为所有的数都在300以内,所以最多也就62种质数,建个线段树记录一下。一开始打算在线段树的每个节点内开个62大小的数组记录每个质数出现的次数,毫无疑问的MLE。

而我们并不需要记录质数出现次数,只需知道哪些质数出现过以及区间乘积,可以利用位压来记录哪些质数出现过,然后区间乘积就是线段树的基本操作了。

#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
const int MAX=4e5+10;
const double PI=acos(-1.0);
typedef long long ll;
vector<int>v;
ll POW(ll x,ll n)
{
    ll res=1;
    while(n)
    {
        if(n&1)res=res*x%MOD;
        x=x*x%MOD;
        n>>=1;
    }
    return res;
}
ll mask[301];
void init()
{
    int vis[301],cnt=0;
    memset(vis,0,sizeof vis);
    memset(mask,0,sizeof mask);
    for(int i=2;i<=300;i++)
    {
        if(vis[i])continue;
        v.push_back(i);
        for(int j=i;j<=300;j+=i)
        {
            vis[j]=1;
            mask[j]|=1ll<<cnt;
        }
        cnt++;
    }
}
pair<ll,ll> H(pair<ll,ll>A,pair<ll,ll>B)
{
    A.first=A.first*B.first%MOD;
    A.second=A.second|B.second;
    return A;
}
struct lenka
{
    int l,r;
    pair<ll,ll>ans;
    pair<ll,ll>lazy;
}A[MAX<<2];
void build(int k,int l,int r)
{
    A[k].l=l,A[k].r=r;
    A[k].lazy={1,0};
    if(l==r)
    {
        int x;
        scanf("%d",&x);
        A[k].ans={x,mask[x]};
        return;
    }
    build(2*k,l,(l+r)/2);
    build(2*k+1,(l+r)/2+1,r);
    A[k].ans=H(A[2*k].ans,A[2*k+1].ans);
}
void change(int k,int x,int y,pair<ll,ll>ans)
{
    if(x==A[k].l&&y==A[k].r)
    {
        A[k].lazy=H(A[k].lazy,ans);
        ans.first=POW(ans.first,y-x+1);
        A[k].ans=H(A[k].ans,ans);
        return;
    }
    if(A[k].lazy.first!=1||A[k].lazy.second!=0)
    {
        change(2*k,A[2*k].l,A[2*k].r,A[k].lazy);
        change(2*k+1,A[2*k+1].l,A[2*k+1].r,A[k].lazy);
        A[k].lazy={1,0};
    }
    if(y<=A[2*k].r)change(2*k,x,y,ans);
    else if(x>=A[2*k+1].l)change(2*k+1,x,y,ans);
    else
    {
        change(2*k,x,A[2*k].r,ans);
        change(2*k+1,A[2*k+1].l,y,ans);
    }
    A[k].ans=H(A[2*k].ans,A[2*k+1].ans);
}
pair<ll,ll> ask(int k,int x,int y)
{
    if(x==A[k].l&&y==A[k].r)return A[k].ans;
    if(A[k].lazy.first!=1||A[k].lazy.second!=0)
    {
        change(2*k,A[2*k].l,A[2*k].r,A[k].lazy);
        change(2*k+1,A[2*k+1].l,A[2*k+1].r,A[k].lazy);
        A[k].lazy={1,0};
    }
    if(y<=A[2*k].r)return ask(2*k,x,y);
    else if(x>=A[2*k+1].l)return ask(2*k+1,x,y);
    return H(ask(2*k,x,A[2*k].r),ask(2*k+1,A[2*k+1].l,y));
}
int main()
{
    init();
    int n,q;
    cin>>n>>q;
    build(1,1,n);
    while(q--)
    {
        char op[10];
        int L,R,x;
        scanf("%s%d%d",op,&L,&R);
        if(op[0]=='M')
        {
            scanf("%d",&x);
            change(1,L,R,make_pair(x,mask[x]));
        }
        else
        {
            pair<ll,ll>now=ask(1,L,R);
            for(int i=0;i<62;i++)
            {
                if((1ll<<i)&now.second)
                {
                    now.first=now.first*POW(v[i],MOD-2)%MOD;
                    now.first=now.first*(v[i]-1)%MOD;
                }
            }
            printf("%lld\n",now.first);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/87109771
今日推荐