BUPT Summer Journey #test7 E

来源:互联网 发布:ubuntu 安装 交换分区 编辑:程序博客网 时间:2024/04/30 16:10

 

 

时间限制 2000 ms 内存限制 65536 KB

题目描述

小弱最近在研究质数,他认为两个数互质是一个好性质。现在hiyot大神为了考考他学习的成果,给了他长度为n的整数序列a1、a2 .. an。同时给了他下面了两种操作:
操作一:"1 l r", 先求出区间[l, r]的所有数的gcd, 再计算[2,m]中有多少个数与gcd互质。
操作二: "2 p x", 把a[p]数值替换为x( 1 <= x <= 1000)
小弱是弱渣,但是如果你做出来了,他会认可你为大神,请你帮他算算。

输入格式

有多组数据。
每组数据以n( 1<=n<=10000), m(2<=m<=1000000), q(1<=q<=10000)开头。接下来一行有n(1 <= ai <= 1000)个数。最后q行每行有三个数,对应于一个操作。

输出格式

对每一个查询输出对应个数(如果区间gcd为1,则输出-1)。

输入样例

5 10 102 2 3 3 51 1 41 3 31 5 51 1 22 3 22 4 21 1 42 3 102 4 101 3 4

输出样例

-16 7443

思路:其实这道题来说的话gcd是容易更新的,难就在处理互质上。有两种处理方式,一种是用容斥原理,另外一种是分区间然后统计。由于时限为2000ms都可以过。

代码:

 

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<vector>#define maxn 20000//#define LOCALusing namespace std;int n,m,q,result,gcd[4*maxn],ans[maxn],a[maxn];int prime[]={0,2,3,5,7,11,13,17,19,23,29,31};vector<int> g[2000];void Init(){    for(int i=2;i<=1000;i++)    {        g[i].clear();int temp=i;        for(int j=1;j<=11;j++)            if(temp%prime[j]==0)            {                while(temp%prime[j]==0)temp/=prime[j];                g[i].push_back(prime[j]);            }        if(temp!=1)g[i].push_back(temp);    }}int solve(int a,int m){    int sz=g[a].size();    int ret=0;    if(sz==1) ret=m-m/g[a][0];    else if(sz==2) ret=m-m/g[a][0]-m/g[a][1]+m/(g[a][0]*g[a][1]);    else if(sz==3){        int a1=g[a][0],a2=g[a][1],a3=g[a][2];        ret=m-m/a1-m/a2-m/a3+m/(a1*a2)+m/(a1*a3)+m/(a2*a3)-m/(a1*a2*a3);    }    else if(sz==4){        int a1=g[a][0],a2=g[a][1],a3=g[a][2],a4=g[a][3];        ret=m-m/a1-m/a2-m/a3-m/a4+m/(a1*a2)+m/(a1*a3)+m/(a1*a4)+m/(a2*a3)+m/(a2*a4)+m/(a3*a4)-m/(a1*a2*a3)-m/(a1*a2*a4)-m/(a1*a3*a4)-m/(a2*a3*a4)+m/(a1*a2*a3*a4);    }    else if(sz==5){        int a1=g[a][0], a2=g[a][1], a3=g[a][2], a4=g[a][3], a5=g[a][4];        ret=m-m/a1-m/a2-m/a3-m/a4-m/a5+m/(a1*a2)+m/(a1*a3)+m/(a1*a4)+m/(a1*a5)+m/(a2*a3)+m/(a2*a4)+m/(a2*a5)+m/(a3*a4)+m/(a3*a5)+m/(a4*a5)-m/(a1*a2*a3)-m/(a1*a2*a4)-m/(a1*a2*a5)-m/(a1*a3*a4)-m/(a1*a3*a5)-m/(a1*a4*a5)-m/(a2*a3*a4)-m/(a2*a3*a5)-m/(a2*a4*a5)-m/(a3*a4*a5)+m/(a1*a2*a3*a4)+m/(a1*a2*a3*a5)+m/(a1*a2*a4*a5)+m/(a1*a3*a4*a5)+m/(a2*a3*a4*a5)-m/(a1*a2*a3*a4*a5);    }    return ret-1;}int Gcd(int a,int b){    if(b==0)return a;    return Gcd(b,a%b);}void build(int l,int r,int Ind){    if(l==r){gcd[Ind]=a[l];return;}    int mid=(l+r)>>1;    build(l,mid,Ind<<1);    build(mid+1,r,(Ind<<1)+1);    gcd[Ind]=Gcd(gcd[Ind<<1],gcd[(Ind<<1)+1]);}void Modify(int a,int l,int r,int Ind,int d){    //printf("Up l=%d r=%d\n",l,r);    if(l==r&&l==a){gcd[Ind]=d;return;}    int mid=(l+r)>>1;    if(a<=mid)Modify(a,l,mid,Ind<<1,d);    else Modify(a,mid+1,r,(Ind<<1)+1,d);    gcd[Ind]=Gcd(gcd[Ind<<1],gcd[(Ind<<1)+1]);    //printf("Down l=%d r=%d gcd[%d]=%d\n",l,r,Ind,gcd[Ind]);}void query(int a,int b,int l,int r,int Ind){    //printf("Up a=%d b=%d l=%d r=%d ",a,b,l,r);printf("result=%d\n",result);    if(a<=l&&r<=b){result=Gcd(result,gcd[Ind]);return;}    int mid=(l+r)>>1;    if(a<=mid)query(a,b,l,mid,Ind<<1);    if(mid<b)query(a,b,mid+1,r,(Ind<<1)+1);    gcd[Ind]=Gcd(gcd[Ind<<1],gcd[(Ind<<1)+1]);    //printf("Down a=%d b=%d l=%d r=%d gcd[%d]=%d\n",a,b,l,r,Ind,gcd[Ind]);printf("result=%d\n",result);}void Cal(){    ans[1]=-1;    for(int i=2;i<=1000;i++)    {        int cnt=0,k=m/i,r=m%i;        for(int j=1;j<i;j++)if(Gcd(i,j)==1)cnt++;        ans[i]=cnt*k-1;        for(int j=1;j<=r;j++)if(Gcd(i,j)==1)ans[i]++;    }    /*ans[1]=-1;    for(int i=2;i<=1000;i++)//可能出现的gcd值    {        int cnt=0,pr=m/i,la=m%i;        for(int j=1;j<i;j++)if(Gcd(i,j)==1)cnt++;        ans[i]=cnt*pr-1;        for(int j=1;j<=la;j++)if(Gcd(i,j)==1)ans[i]++;    }*/}int main(){    #ifdef LOCAL    freopen("input.txt","r",stdin);    #endif // LOCALf    while(scanf("%d%d%d",&n,&m,&q)==3)    {        int kind,l,r,x,v;        for(int i=1;i<=n;i++)scanf("%d",&a[i]);        build(1,n,1);        Init();        //for(int i=1;i<=10;i++)printf("gcd[%d]=%d\n",i,gcd[i]);        //cout<<query(1,2,1,n,1)<<endl;        //Cal();        for(int i=1;i<=q;i++)        {            scanf("%d",&kind);            if(kind==1)            {                scanf("%d%d",&l,&r);                result=a[r];query(l,r,1,n,1);                if(result==1)printf("-1\n");                else                {                    int ret=solve(result,m);                    printf("%d\n",ret);                }            }            if(kind==2){scanf("%d%d",&x,&v);a[x]=v;Modify(x,1,n,1,v);}        }     }    return 0;}


//////////////////////////////////////////////////////////////////////////////////////////////////////

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<vector>#define maxn 20000//#define LOCALusing namespace std;int n,m,q,result,gcd[4*maxn],ans[maxn],a[maxn];int prime[]={0,2,3,5,7,11,13,17,19,23,29,31};vector<int> g[2000];template<class T>inline bool read(T &n){    T x=0,tmp=1;char c=getchar();    while((c<'0'||c>'9')&&c!='-'&&c!=EOF)c=getchar();    if(c==EOF)return false;    if(c=='-')c=getchar(),tmp=-1;    while(c>='0'&&c<='9')x*=10,x+=(c-'0'),c=getchar();    n=x*tmp;return true;}template<class T>inline void write(T n){    if(n<0){putchar('-');n=-n;}    int len=0,data[20];    while(n){data[len++]=n%10;n/=10;}    if(!len)data[len++]=0;    while(len--)putchar(data[len]+'0');}void Init(){    for(int i=2;i<=1000;i++)    {        g[i].clear();int temp=i;        for(int j=1;j<=11;j++)            if(temp%prime[j]==0)            {                while(temp%prime[j]==0)temp/=prime[j];                g[i].push_back(prime[j]);            }        if(temp!=1)g[i].push_back(temp);    }}int solve(int a,int m){    int sz=g[a].size();    int ret=0;    if(sz==1) ret=m-m/g[a][0];    else if(sz==2) ret=m-m/g[a][0]-m/g[a][1]+m/(g[a][0]*g[a][1]);    else if(sz==3){        int a1=g[a][0],a2=g[a][1],a3=g[a][2];        ret=m-m/a1-m/a2-m/a3+m/(a1*a2)+m/(a1*a3)+m/(a2*a3)-m/(a1*a2*a3);    }    else if(sz==4){        int a1=g[a][0],a2=g[a][1],a3=g[a][2],a4=g[a][3];        ret=m-m/a1-m/a2-m/a3-m/a4+m/(a1*a2)+m/(a1*a3)+m/(a1*a4)+m/(a2*a3)+m/(a2*a4)+m/(a3*a4)-m/(a1*a2*a3)-m/(a1*a2*a4)-m/(a1*a3*a4)-m/(a2*a3*a4)+m/(a1*a2*a3*a4);    }    else if(sz==5){        int a1=g[a][0], a2=g[a][1], a3=g[a][2], a4=g[a][3], a5=g[a][4];        ret=m-m/a1-m/a2-m/a3-m/a4-m/a5+m/(a1*a2)+m/(a1*a3)+m/(a1*a4)+m/(a1*a5)+m/(a2*a3)+m/(a2*a4)+m/(a2*a5)+m/(a3*a4)+m/(a3*a5)+m/(a4*a5)-m/(a1*a2*a3)-m/(a1*a2*a4)-m/(a1*a2*a5)-m/(a1*a3*a4)-m/(a1*a3*a5)-m/(a1*a4*a5)-m/(a2*a3*a4)-m/(a2*a3*a5)-m/(a2*a4*a5)-m/(a3*a4*a5)+m/(a1*a2*a3*a4)+m/(a1*a2*a3*a5)+m/(a1*a2*a4*a5)+m/(a1*a3*a4*a5)+m/(a2*a3*a4*a5)-m/(a1*a2*a3*a4*a5);    }    return ret-1;}int Gcd(int a,int b){    if(b==0)return a;    return Gcd(b,a%b);}void build(int l,int r,int Ind){    if(l==r){gcd[Ind]=a[l];return;}    int mid=(l+r)>>1;    build(l,mid,Ind<<1);    build(mid+1,r,(Ind<<1)+1);    gcd[Ind]=Gcd(gcd[Ind<<1],gcd[(Ind<<1)+1]);}void Modify(int a,int l,int r,int Ind,int d){    //printf("Up l=%d r=%d\n",l,r);    if(l==r&&l==a){gcd[Ind]=d;return;}    int mid=(l+r)>>1;    if(a<=mid)Modify(a,l,mid,Ind<<1,d);    else Modify(a,mid+1,r,(Ind<<1)+1,d);    gcd[Ind]=Gcd(gcd[Ind<<1],gcd[(Ind<<1)+1]);    //printf("Down l=%d r=%d gcd[%d]=%d\n",l,r,Ind,gcd[Ind]);}void query(int a,int b,int l,int r,int Ind){    //printf("Up a=%d b=%d l=%d r=%d ",a,b,l,r);printf("result=%d\n",result);    if(a<=l&&r<=b){result=Gcd(result,gcd[Ind]);return;}    int mid=(l+r)>>1;    if(a<=mid)query(a,b,l,mid,Ind<<1);    if(mid<b)query(a,b,mid+1,r,(Ind<<1)+1);    gcd[Ind]=Gcd(gcd[Ind<<1],gcd[(Ind<<1)+1]);    //printf("Down a=%d b=%d l=%d r=%d gcd[%d]=%d\n",a,b,l,r,Ind,gcd[Ind]);printf("result=%d\n",result);}void Cal(){    ans[1]=-1;    for(int i=2;i<=1000;i++)    {        int cnt=0,k=m/i,r=m%i;        for(int j=1;j<i;j++)if(Gcd(i,j)==1)cnt++;        ans[i]=cnt*k-1;        for(int j=1;j<=r;j++)if(Gcd(i,j)==1)ans[i]++;    }    /*ans[1]=-1;    for(int i=2;i<=1000;i++)//可能出现的gcd值    {        int cnt=0,pr=m/i,la=m%i;        for(int j=1;j<i;j++)if(Gcd(i,j)==1)cnt++;        ans[i]=cnt*pr-1;        for(int j=1;j<=la;j++)if(Gcd(i,j)==1)ans[i]++;    }*/}int main(){    #ifdef LOCAL    freopen("input.txt","r",stdin);    #endif // LOCALf    while(read(n))    {        read(m);read(q);        int kind,l,r,x,v;        for(int i=1;i<=n;i++)read(a[i]);        build(1,n,1);        Init();        for(int i=1;i<=q;i++)        {            read(kind);            if(kind==1)            {                read(l);read(r);                result=a[r];query(l,r,1,n,1);                if(result==1){write(-1);printf("\n");}                else                {                    int ret=solve(result,m);                    write(ret);printf("\n");                }            }            if(kind==2){read(x);read(v);a[x]=v;Modify(x,1,n,1,v);}        }     }    return 0;}


 

0 0
原创粉丝点击