Sum(hdu4407)
2016-05-04 21:30
465 查看
Sum
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2974 Accepted Submission(s): 843
[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
思路:容斥原理;
因为原数列是[1,n];所以数的和我们可以直接用求和公式;
然后m<1000;所以改变的最多不超过1000;我们用数组存改变,改变的位置会重复,这时后要覆盖,也就是数组中原先已有这个点,我们可以用map标记是否在数组中已有;
没有的话加入,有的话覆盖。
然后询问是[x,y]区间内与z互质的数的和,所以我们考虑分解z,那么素数打表。
然后容斥求在[x,y]与z互质数的和;然后再循环一遍改变,判断替换的数,和原来的数是否与z互质,原来的数互质的话减去原来的,改变的数互质的话,加上改变的数;
每个数的不同的质因数不超过9个;
复杂度(5120*m);
#include<stdio.h> #include<algorithm> #include<iostream> #include<stdlib.h> #include<string.h> #include<queue> #include<map> typedef long long LL; using namespace std; bool prime[400005]; int ans[400005]; queue<int>que; int cm[400005]; int ma[400005]; int flag[2000]; int gcd(int n,int m); map<int,int>my; int main(void) { int i,j,k; int p,q; int n,m; int x,y; int t; for(i=2; i<=2000; i++) { if(!prime[i]) { for(j=i; i*j<=400000; j++) { prime[i*j]=true; } } } int cnt=0; for(i=2; i<=400000; i++) { if(!prime[i]) { ans[cnt++]=i; } } scanf("%d",&k); while(k--) { my.clear(); scanf("%d %d",&p,&q); int bt=1; for(i=0; i<=p; i++) ma[i]=i; while(q--) { scanf("%d",&n); if(n==1) { scanf("%d %d %d",&x,&y,&t); int r=0; int yy=0; int xy=t; if(x>y)swap(x,y); while(t>1) { if(r==0&&t%ans[yy]==0) { r=1; que.push(ans[yy]); t/=ans[yy]; } else if(r==1&&t%ans[yy]==0) { t/=ans[yy]; } else { r=0; yy++; } } x-=1; int ak=0; while(!que.empty()) { cm[ak++]=que.front(); que.pop(); } LL sum1=0; LL sum2=0; for(i=1; i<=(1<<ak)-1; i++) { int nn=0; LL dp=1; for(j=0; j<ak; j++) { if(i&(1<<j)) { nn++; dp*=(LL)cm[j]; } } if(nn%2) { LL ct=y/dp; LL qt=x/dp; LL ct1=ct+1; LL qt1=qt+1; sum1+=dp*ct1*ct/2; sum2+=dp*qt1*qt/2; } else { LL ct=y/dp; LL qt=x/dp; LL ct1=ct+1; LL qt1=qt+1; sum1-=dp*ct1*ct/2; sum2-=dp*qt1*qt/2; } } LL xc=1+x;LL yc=1+y; LL ap1=(long long )(xc)*(long long)x/2; LL ap2=(long long)(yc)*(long long)y/2; ap2-=sum1; ap1-=sum2; ap2-=ap1; for(j=1; j<bt; j++) { if(flag[j]>=x+1&&flag[j]<=y) { int cp=gcd(xy,ma[flag[j]]); int cq=gcd(xy,flag[j]); if(cq==1) ap2-=flag[j]; if(cp==1) ap2+=ma[flag[j]]; } } printf("%lld\n",ap2); } else { scanf("%d %d",&x,&t); if(my[x]==0) {my[x]=1;flag[bt]=x;bt++;} ma[x]=t; } } } return 0; } int gcd(int n,int m) { if(m==0) return n; else if(n%m==0) return m; else return gcd(m,n%m); }
相关文章推荐
- RTT常用数据类型
- Android开发中重要的类
- C++模板
- Java在硬盘上创建一个文件并写入一些文字数据FileWriter
- 一个 while 实现 C 翻转单向链表
- Machine Learning -01 --Introduction 机器学习介绍
- [暴力] BZOJ 3917 [Baltic2014]sequence
- argmax()
- 涂书笔记-让读书笔记不再困难
- uC/OS 的进程调度(下)
- 官网下载及安装mysql-5.7.12-winx64是需要解压版(ZIP)
- Java-常用方法汇总
- ios - kvo观察者示例
- HDU 2126 01背包(求方案数)
- Redis 事务
- 使用keychain保存用户名和密码等敏感信息 KeychainItemWrapper和SFHFKeychainUtils。
- IDEA错误:Cannot start compilation: the output path is not specified for module "Test". Specify the out
- SQL Server 查询数据库中所有的表名及行数
- SQL Server 查询数据库中所有的表名及行数
- List