您的位置:首页 > 其它

HDU 4407 Sum 容斥原理

2013-10-23 15:40 381 查看

Sum

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

[align=left]Problem Description[/align]
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.

[align=left]Input[/align]
There are several test cases. The first line in the input is an integer indicating the number of test cases. For each case, the first line begins with two integers --- the above mentioned n and m. 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".

[align=left]Output[/align]
For each operation 1, output a single integer in one line representing the result.

[align=left]Sample Input[/align]

1
3 3
2 2 3
1 1 3 4
1 2 3 6

[align=left]Sample Output[/align]

7
0

[align=left]Source[/align]
2012 ACM/ICPC Asia Regional Jinhua Online

#include <iostream>
#include <stdio.h>
#include <queue>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#include <set>
#include <algorithm>
#include <map>
#include <stack>
#include <math.h>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std ;
typedef long long LL ;
const int M_P=1008 ;
bool isprime[M_P+8] ;
int prime[M_P] ,id ;
void make_prime(){
id=0 ;
memset(isprime,0,sizeof(isprime))  ;
for(int i=2;i<=M_P;i++){
if(!isprime[i])
prime[++id]=i  ;
for(int j=1;j<=id&&i*prime[j]<=M_P;i++){
isprime[i*prime[j]]=1 ;
if(i%prime[j]==0)
break ;
}
}
}
int gcd(int x ,int y){
return y==0?x:gcd(y,x%y) ;
}
struct Change{
int id ;
int num ;
};
vector<Change>query ;
inline LL Sum(LL N){
return N*(1+N)/2 ;
}
LL gao(int N ,int P){
vector<int>vec ;
vec.clear() ;
LL ans=0 ;
LL M=P ;
for(int i=1;i<=id&&prime[i]*prime[i]<=M;i++){
if(M%prime[i]==0){
vec.push_back(prime[i]) ;
while(M%prime[i]==0)
M/=prime[i]  ;
}
if(M==1)
break ;
}
if(M!=1)
vec.push_back(M) ;
int n=vec.size() ;
for(int i=1;i<(1<<n);i++){
int now=0 ;
int pri=1 ;
for(int j=0;j<n;j++){
if(i&(1<<j)){
now++ ;
pri*=vec[j] ;
}
}
if(now&1)
ans=ans+pri*Sum(N/pri) ;
else
ans=ans-pri*Sum(N/pri) ;
}
return Sum(N)-ans ;
}
map<int ,int>my_hash ;
int main(){
make_prime() ;
int L ,R ,P ,N ,M ,T ,kind;
scanf("%d",&T) ;
while(T--){
scanf("%d%d",&N,&M) ;
query.clear() ;
while(M--){
scanf("%d",&kind) ;
if(kind==1){
scanf("%d%d%d",&L,&R,&P) ;
if(L>R)
swap(L ,R) ;
LL ans=gao(R,P)-gao(L-1,P) ;
my_hash.clear() ;
for(int i=0;i<query.size();i++){
int ID=query[i].id ;
int Num=query[i].num ;
if(L<=ID&&ID<=R){
if(my_hash.find(ID)==my_hash.end()){
if(gcd(ID,P)==1)
ans-=ID ;
}
else{
LL now_num = my_hash[ID] ;
if(gcd(now_num,P)==1)
ans-=now_num ;
}
if(gcd(Num,P)==1)
ans+=Num ;
my_hash[ID]=Num ;
}
}
printf("%I64d\n",ans) ;
}
else{
Change now ;
scanf("%d%d",&now.id,&now.num) ;
query.push_back(now) ;
}
}
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: