标签:hdu
http://acm.hdu.edu.cn/showproblem.php?pid=4407
1 3 3 2 2 3 1 1 3 4 1 2 3 6
7 0
分析:如果没有第二个操作,那么求[x,y]区间可以直接用容斥求1到x-1和1到y的分别有多少个与p互质的,结果一减就好。对于操作2,由于总操作数只有m<=1000次,那么我们可以用一个map记录修改的数,然后暴力扫一遍map每一个数,map[a]=b,若a在区间[x,y]内,a与p互质,则答案减1,b与p互质则加1.。。
/** * @author neko01 */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <string.h> #include <iostream> #include <algorithm> #include <queue> #include <vector> #include <cmath> #include <set> #include <map> using namespace std; typedef long long LL; #define min3(a,b,c) min(a,min(b,c)) #define max3(a,b,c) max(a,max(b,c)) #define pb push_back #define mp(a,b) make_pair(a,b) #define clr(a) memset(a,0,sizeof a) #define clr1(a) memset(a,-1,sizeof a) #define dbg(a) printf("%d\n",a) typedef pair<int,int> pp; const double eps=1e-9; const double pi=acos(-1.0); const int INF=0x7fffffff; const LL inf=(((LL)1)<<61)+5; int n,m; const int M=1000; bool isprime[M]; int prime[M]; int fac[25]; int tot=0,num; map<int,int>mp; map<int,int>::iterator it; int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } void getprime() { for(int i=2;i<=M;i++) { if(isprime[i]) continue; prime[tot++]=i; for(int j=i*i;j<=M;j+=i) isprime[j]=true; } } LL gao(int x) { LL sum=0; for(int i=1;i<(1<<num);i++) { int tmp=1,op=0; for(int j=0;j<num;j++) { if((1<<j)&i) { op++; tmp*=fac[j]; } } if(op&1) { LL k=x/tmp; sum+=(tmp+k*tmp)*k/2; } else { LL k=x/tmp; sum-=(tmp+k*tmp)*k/2; } } return 1LL*x*(1+x)/2-sum; } void getfac(int x) { num=0; for(int i=0;i<tot&&prime[i]*prime[i]<=x;i++) { if(x%prime[i]==0) { fac[num++]=prime[i]; while(x%prime[i]==0) x/=prime[i]; } } if(x>1) fac[num++]=x; } LL getans(int a,int b,int p) { LL ans=gao(b)-gao(a-1); for(it=mp.begin();it!=mp.end();it++) { if(it->first<a||it->first>b||it->first==it->second) continue; if(gcd(it->first,p)==1) ans-=it->first; if(gcd(it->second,p)==1) ans+=it->second; } return ans; } int main() { int t; scanf("%d",&t); getprime(); while(t--) { scanf("%d%d",&n,&m); mp.clear(); for(int i=1;i<=m;i++) { int xx,x,y,p; scanf("%d",&xx); if(xx==1) { scanf("%d%d%d",&x,&y,&p); getfac(p); printf("%I64d\n",getans(x,y,p)); } else { scanf("%d%d",&x,&y); mp[x]=y; } } } return 0; }
标签:hdu
原文地址:http://blog.csdn.net/neko01/article/details/40682239