446. 大神题
时间限制 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 10
2 2 3 3 5
1 1 4
1 3 3
1 5 5
1 1 2
2 3 2
2 4 2
1 1 4
2 3 10
2 4 10
1 3 4
输出样例
-1
6
7
4
4
3
思路:其实这道题来说的话gcd是容易更新的,难就在处理互质上。有两种处理方式,一种是用容斥原理,另外一种是分区间然后统计。由于时限为2000ms都可以过。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#define maxn 20000
//#define LOCAL
using 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 LOCAL
using 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;
}