您的位置:首页 > 其它

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