标签: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