您的位置:首页 > 其它

HDU 4407 Sum【容斥原理】

2012-09-24 18:36 417 查看
题意: 有n 个数从1 到 n 有序排好,对应两种操作:

1 x y p 找出区间【x,y】内与 p 互质的数的和

2 x c 将第x位置的数变成 c

分析: 由于修改的次数比较少,可以先计算出没有修改时候指定区间内与p 互质的数的和,再去根据替换的数去修改,

找出连续数字区间内与p 互质数的和可以先将p分解质因数,然后用容斥原理快速的计算出区间满足条件的数的

和即可。

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
#define maxn 400005
bool v[maxn];
int pri[maxn];
int top;
void print()
{
memset(v,true,sizeof(v));
int i,j;
top=0;
pri[top++]=2;
v[4]=false;
for(i=3;i<=400000;i++)
{
if(v[i])
pri[top++]=i;
for(j=0;j<top&&pri[j]*i<=400000;j++)
{
v[pri[j]*i]=false;
if(i%pri[j]==0)
break;
}
}
}
long long get(int now,int n)
{
long long tmp=(long long)n/now;
return (long long)now*tmp*(tmp+1)/2;
}
int gcd(int y,int x)
{
return x==0?y:gcd(x,y%x);
}
long long q[maxn];
long long solve(int n,int p)
{
int cnt=0;
int i=0,j;
while(pri[i]*pri[i]<=p&&i<top)
{
int tmp=pri[i];
if(p%tmp==0)
{
q[++cnt]=tmp;
while(p%tmp==0)
p/=tmp;
}
i++;
}
if(p>1)
q[++cnt]=p;
int st=1<<cnt;
long long res;
res=get(1,n);
for(i=1;i<st;i++)
{
int tmp=1;
int count=0;
int now=1;
for(j=1;j<=cnt;j++)
{
if(i&tmp)
{
count++;
now*=q[j];
}
tmp<<=1;
}
if(count&1)
res-=get(now,n);
else
res+=get(now,n);
}
return res;
}
struct node
{
int xu,x,y;
}ti[maxn];
int id[maxn];
int main()
{
int i,t,n,m;
int op;
print();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(id,-1,sizeof(id));
int cnt=0;
while(m--)
{
scanf("%d",&op);
int x,y,p;
if(op==1)
{
scanf("%d%d%d",&x,&y,&p);
long long res=0;
res=solve(y,p);
res=res-solve(x-1,p);
for(i=0;i<cnt;i++)
if(ti[i].x>=x&&ti[i].x<=y)
{
int tx=ti[i].x;
int ty=ti[i].y;
if(gcd(tx,p)==1)
res-=tx;
if(gcd(ty,p)==1)
res+=ty;
}
printf("%I64d\n",res);
}
else
{
scanf("%d%d",&x,&y);
if(id[x]==-1)
{
id[x]=cnt;
ti[cnt].x=x;
ti[cnt++].y=y;
}
else
{
ti[id[x]].x=x;
ti[id[x]].y=y;
}
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: