Sum(HDU 4407)
XXX is puzzled with the question below:
1, 2, 3, ..., n (1<=n<=400000) are placed in a line. There are m (1<=m<=1000) operations of two kinds.
Operation 1: among the x-th number to the y-th number (inclusive), get the sum of the numbers which are co-prime with p( 1 <=p <= 400000).
Operation 2: change the x-th number to c( 1 <=c <= 400000).
For each operation, XXX will spend a lot of time to treat it. So he wants to ask you to help him.
Input
There are several test cases.
The first line in the input is an integer indicating the number of test cases.
Each the following m lines contains an operation.
Operation 1 is in this format: "1 x y p".
Operation 2 is in this format: "2 x c".
Output
1 3 3 2 2 3 1 1 3 4 1 2 3 6
7 0
题意:
一个长度为n的序列,开始的序列为1,2,3....n;
然后又两种操作。
operation1: 询问区间[a,b]中与p互质的数的和。
operation2:将序号为i的数修改为x;
如果没有修改操作,那么狠明显就是一个容斥原理
计数的问题。
这里用到了map,map既保存了未修改前的数,又保存了修改之后的数,具有对应关系。。至于修改,由于修改次数比较小,把修改存起来,对于每个查询,一个个改过去。
#include<cstdio>
#include<vector>
#include<iostream>
#include<map>
using namespace std;
vector<int>x;
map<int,int>Map;
void getPrimeFactor(int n)///对n进行素因子的分解
{ ///容斥原理的必须步骤
x.clear();
for(int i=2;i*i<=n;i++)
if(n%i==0)
{
x.push_back(i);
while(n%i==0)
n/=i;
}
if(n!=1)
x.push_back(n);
}
bool gcd(int a,int b)///判断两个数是否互质
{ ///互质返回true;否则返回false;
while(b)
{
int t=a;
a=b;
b=t%b;
}
if(a==1)
return true;
else
return false;
}
long long solve(int b,int p)///容斥原理的简单变形,要求的不是互质的个数
{ ///而是互质数的和
long long ans=(long long)b*(1+b)/2;
long long sum=0;
for(int i=1;i<(1<<x.size());i++)
{
int cnt=0;
long long k=1;
for(int j=0;j<x.size();j++)
if(i&(1<<j))
{
cnt++;
k*=x[j];
}
k=(b/k)*(k+(b/k)*k)/2;
if(cnt&1)
sum+=k;
else
sum-=k;
}
return ans-sum;
}
long long sub(long long ans,int a,int b,int p)///修改
{
map<int,int>::iterator it;
for(it=Map.begin();it!=Map.end();it++)
{
int f1=gcd(p,it->second);
int f2=gcd(p,it->first);
if(it->first<=b&&it->first>=a)
{
if(f1) ans+=it->second;
if(f2) ans-=it->first;
}
}
return ans;
}
int main()
{
int t;
cin>>t;
int n,m;
while(t--)
{
Map.clear();
scanf("%d%d",&n,&m);
int x,y,p;
while(m--)
{
scanf("%d",&x);
if(x==1)
{
scanf("%d%d%d",&x,&y,&p);
getPrimeFactor(p);
cout<<sub(solve(y,p)-solve(x-1,p),x,y,p)<<endl;
}
else
{
scanf("%d%d",&x,&p);
Map[x]=p;
}
}
}
return 0;
}