您的位置:首页 > 其它

解题报告: HDU_4407 Sum 容斥+暴力

2016-11-09 11:59 330 查看

Sum

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

Total Submission(s): 3292    Accepted Submission(s): 957


[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

 

[align=left]Recommend[/align]
zhoujiaqi2010
 

Statistic | Submit | Discuss
| Note

题意:
T组数据,给一个1~n的序列,m次操作,操作只有两种:
1. 查询 [ L , R ] 中与 P 互质的数的和
2. 将第a个数改成b

汗....我记得明明写过一次这题的解题报告了....竟然没有....那就重新写一份吧.....

思路:
先考虑如果没有修改操作的话,容斥应该是可以解决操作1的查询:
处理出P的素因子,然后ANS = (区间总和)  - (区间和单个素因子不互素的数总和) + (区间和两个素因子的乘积不互素的数的总和) ```````
奇减偶加
然后考虑m只有1000,那么每次就先看做原序列进行容斥操作然后遍历一遍之前的所有修改操作,将对应在查询区间里的该加的加,该减的减就好了。

代码:
#include<bits/stdc++.h>
using namespace std;
/******
!!!!!!!!
Remember !!!;
use init() function
/***** o(n) ******/

namespace prime_table{

const int MAX_N = 4e5;

int all;
int pr[MAX_N/10+100];
bool isp[MAX_N+10];

inline void init(){
all = 0;
memset(isp,0,sizeof(isp));
for(int i=2;i<=MAX_N;i++){
if(!isp[i]){
pr[all++] = i;
}for(int j=0;j<all;j++){
long long t = 1LL*pr[j]*i ;
if(t<=MAX_N){
isp[t] = true;
if(i%pr[j]==0)break;
}else {
break;
}
}
}
return ;
}

}
using namespace prime_table;

/*****
Fundamental Theorem of Arithmetic
*****/
int cnt;
int e[100];
inline void oper(int x){
int m =sqrt(x+0.5);cnt = 0;
for(int i=0;i<all&&pr[i]<=m&&pr[i]<=x;i++){
if(x%pr[i]==0){
e[cnt++] = pr[i];
do{x/=pr[i];}
while(x%pr[i]==0);
}
}if(x!=1){
e[cnt++] = x;
}return ;
}
int A[1005][2];
bool hasChange[400005];
long long ans ;

inline long long work(int l,int x){
int num = l/x;
return 1LL*(1+num)*num/2*x;
}

inline void dfs(int id,int val,int need,int has,const int &L,const int &R){
if(need==has){
ans += (need&1?1LL:-1LL)*(work(R,val)-work(L-1,val));
return ;
}for(int i=id;i<cnt;i++){
dfs(i+1,val*e[i],need,has+1,L,R);
}return ;
}

int main(){
int T;init();
scanf("%d",&T);
while(T--){
memset(hasChange,0,sizeof(hasChange));
int n,m,num=0;
scanf("%d%d",&n,&m);
while(m--){
int a,b,c,k;
scanf("%d%d%d",&k,&a,&b);
if(k==1){
scanf("%d",&c);
ans=0;
oper(c);
/*
for(int i=0;i<cnt;i++){
printf("e[%d]-->%d\n",i,e[i]);
}*/
for(int i=1;i<=cnt;i++){
dfs(0,1,i,0,a,b);
}ans = 1LL*(a+b)*(b-a+1)/2 - ans;
for(int i=0;i<num;i++){
if(A[i][0]>=a&&A[i][0]<=b){
if(__gcd(A[i][0],c)==1)
ans -= A[i][0];
if(__gcd(A[i][1],c)==1){
ans += A[i][1];
}
}
}printf("%I64d\n",ans);
}else {
if(hasChange[a]){
for(int i=0;i<num;i++){
if(A[i][0]==a){
A[i][1]=b;
break;
}
}
}else {
A[num][0]=a;
A[num++][1]=b;
hasChange[a]=true;
}

}
}
}return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: