标签:des style blog class code java
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4407
1 3 3 2 2 3 1 1 3 4 1 2 3 6
7 0
题目意思:
开始有1~n的n(n<=40000)个数,有两种操作
操作1: 1 x y p 求在区间[x,y]之间和p互质的所有数的和
操作2: 2 x c 把x位置上的数改成c
解题思路:
简单容斥原理
实际上题目要求的就是求1~x间和p互质的数的总和。可以先把p分解质因数,然后用容斥原理求出与p不互质的总和,用总和减去即可。
至于改变,只需保存改变的数值,然后对每个查询扫一遍,单独处理改变的就行了。
代码:
//#include<CSpreadSheet.h>
#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define Maxn 410000
bool isp[Maxn];
ll pri[Maxn],pp[Maxn],cnt0,cnt;
ll x,y;
ll ans1,ans2;
map<int,int>myp;
int cc,n,m,p;
struct Cha
{
int old,ne;
}cha[1100];
void init() //打质数表
{
cnt=0;
int N=400000;
for(int i=1;i<=N;i++)
isp[i]=true;
for(int i=2;i<=N;i++)
{
if(isp[i])
{
pri[++cnt]=i;
for(int j=i*2;j<=N;j+=i)
isp[j]=false;
}
}
}
void cal(ll cur) //分解质因数
{
cnt0=0;
for(int i=1;pri[i]*pri[i]<=cur;i++)
{
if(!(cur%pri[i]))
{
pp[++cnt0]=pri[i];
while(!(cur%pri[i]))
cur/=pri[i];
}
}
if(cur!=1)
pp[++cnt0]=cur;
}
void dfs(ll hav,int cur,int num) //容斥原理求出不互质的
{
if((hav>x&&hav>y)||cur>cnt0)
return ;
for(int i=cur;i<=cnt0;i++)
{
ll next=hav*pp[i];
ll tt1=y/next,tt2=x/next;
if(num&1)
{
ans1-=(1+tt1)*tt1/2*next;
ans2-=(1+tt2)*tt2/2*next;
}
else
{
ans1+=(1+tt1)*tt1/2*next;
ans2+=(1+tt2)*tt2/2*next;
}
dfs(next,i+1,num^1);
}
}
ll gcd(ll a,ll b)
{
if(a%b==0)
return b;
return gcd(b,a%b);
}
int main()
{
//printf("%I64d\n",gcd(12,18));
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
init();
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
myp.clear();
cc=0;
while(m--)
{
int a;
scanf("%d",&a);
if(a==1)
{
scanf("%I64d%I64d%I64d",&x,&y,&p);
if(x>y)
swap(x,y);
x--; //注意x要减一
cal(p);
ll ans;
ans1=(1+y)*y/2,ans2=(1+x)*x/2;
for(int i=1;i<=cnt0;i++)
{
ll tt1=y/pp[i],tt2=x/pp[i];
ans1-=(1+tt1)*tt1/2*pp[i];
ans2-=(1+tt2)*tt2/2*pp[i];
dfs(pp[i],i+1,0);
}
ans=ans1-ans2;
for(int i=1;i<=cc;i++)
{
if(cha[i].ne!=cha[i].old&&cha[i].old<=y&&cha[i].old>x) //要在[x,y]范围内找,x已经减了1
{
if(gcd(cha[i].old,p)==1) //之前已经加了
ans-=cha[i].old;
if(gcd(cha[i].ne,p)==1) //改了过后是否要加上
ans+=cha[i].ne;
}
}
printf("%I64d\n",ans);
}
else
{
scanf("%d%d",&x,&y);
if(myp.find(x)==myp.end())
{
++cc;
myp[x]=cc;
cha[cc].ne=y,cha[cc].old=x;
}
else
cha[myp[x]].ne=y;
}
}
}
return 0;
}
[容斥原理] hdu 4407 Sum,布布扣,bubuko.com
标签:des style blog class code java
原文地址:http://blog.csdn.net/cc_again/article/details/25335033