标签:blog io ar os sp for 2014 log 代码
题意:
有两种操作1,2
1:询问 x,y区间能与p互质的数的和
2:将x改成p
一开始给N,初始是1~N个数
思路:
我们在求不互质的数有多少个的时候 其实就可以用等差数列求和求出这些数的和
那么我们到时候直接求一下就好了
然后因为这里的操作次数很少 所以我们可以标记一下哪些位置被修改过
然后在1操作的时候 特判一下这些位置
代码:
#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
#define ll __int64
#define N 400000
int ss[N+2],v[N+2];
int mark[N+5][10],mcnt[N+5],c[10];
int used[N+5],change[N+5];
int n,chacnt;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int ssb()
{
int cnt=0;
memset(ss,0,sizeof(ss));
for(int i=2;i<=N;i++)
{
if(ss[i]==0)
{
for(int j=i+i;j<=N;j+=i) ss[j]=1;
v[cnt++]=i;
}
}
return cnt;
}
ll dfs(int k,int t,int lit,ll x,ll y,int p)
{
ll ans=0;
if(t==lit)
{
ll tep=1;
for(int i=0;i<lit;i++) tep*=c[i];
ll a=(tep+(x-1)/tep*tep)*((x-1)/tep)/2;
ll b=(tep+y/tep*tep)*(y/tep)/2;
return b-a;
}
for(int i=k+1;i<mcnt[p];i++)
{
c[t]=mark[p][i];
ans+=dfs(i,t+1,lit,x,y,p);
}
return ans;
}
ll solve(ll x,ll y,int p)
{
ll ans=0,tep=((1+y)*y/2)-((x)*(x-1)/2);
for(int i=1;i<=mcnt[p];i++)
{
if(i%2) ans+=dfs(-1,0,i,x,y,p);
else ans-=dfs(-1,0,i,x,y,p);
}
ans=tep-ans;
for(int i=0;i<chacnt;i++)
{
if(change[i]>=x&&change[i]<=y)
{
if(gcd(change[i],p)==1) ans-=change[i];
if(gcd(used[change[i]],p)==1) ans+=used[change[i]];
}
}
return ans;
}
int main()
{
int t,sscnt;
cin>>t;
sscnt=ssb();
memset(mcnt,0,sizeof(mcnt));
for(int i=0;i<sscnt;i++)
{
for(int j=v[i];j<=N;j+=v[i])
{
mark[j][mcnt[j]++]=v[i];
}
}
while(t--)
{
int m;
chacnt=0;
scanf("%d%d",&n,&m);
memset(used,0,sizeof(used));
while(m--)
{
int f,x,y,p;
scanf("%d",&f);
if(f==1)
{
scanf("%d%d%d",&x,&y,&p);
printf("%I64d\n",solve(x,y,p));
}
else
{
scanf("%d%d",&x,&p);
if(used[x]==0) change[chacnt++]=x;
used[x]=p;
}
}
}
return 0;
}
标签:blog io ar os sp for 2014 log 代码
原文地址:http://blog.csdn.net/wdcjdtc/article/details/40897847