hdu 4407 sum

//2012金华网赛 1008

      今天居然挂在了09了 ,n^3的算法 呀,不知道自己写挫了,还是爆rp了,居然老是t;话说这道题目也写得很挫。  这道题有个很好的性质1..n连续 。而且询问又很少,所以直接先求出原数组中(即1..n) 与p互质的数的和,具体肿么求可以用容斥原理。然后枚举被改变的数。

#include<stdio.h>   
#include<string.h>   
#include <cmath>
#include <iostream>
#include<algorithm>   
#define fr(i,s,n) for(int i=s;i<n;i++)
#define pf printf
#define sf scanf
#define fi freopen("in.txt","r",stdin)
#define cl(a) memset(a,0,sizeof(a))
using namespace std;
typedef __int64 ll;

struct C{
	int pos;
	int val;
}c[1000];

int t;  
ll prime[600],tot[400010],n;
bool flag[650];
int N,m;
void init(){
	int i,j;
	t=0;
	int n=632;
	for(i=2;i<=n;++i) { 
		if(!flag[i]) prime[t++]=i; 
		for(j=0;j<t&&i*prime[j]<=n;++j)
		{ 
			flag[i*prime[j]]=1; 
			if(i%prime[j]==0) break; 
		} 
	} 
	tot[0]=0;tot[1]=1;
	fr(i,2,400001) {
		tot[i]=tot[i-1]+i;
	}
}
ll sum(ll lim,ll x){   
	lim/=x;
	ll ret=0;
	ret=ret+(1+lim)*lim/2;
	return ret*x;
}	
ll yinshu[650];
int totyinshu;
void sep(ll p){
	totyinshu=0;
	ll tmp=p;
	fr(i,0,t){
		if (tmp==1) break;
		if(tmp%prime[i]==0){
			yinshu[totyinshu++]=prime[i];
			while(tmp%prime[i]==0){
				tmp/=prime[i];
			}
		}
	}
	if (tmp!=1){
		yinshu[totyinshu++]=tmp;
	}
}
ll dfs(int s,ll d){
	ll ans=0;
	while(s<totyinshu&& yinshu[s]<=n/d){
		ans+=sum(n,d*yinshu[s])-dfs(s+1,d*yinshu[s]);
		s++;
	}
	return ans;
}

int totch;
void change(int x,int y){
	fr(i,0,totch){
		if (c[i].pos==x){
			c[i].val=y;
			return ;
		}
	}
	c[totch].pos=x;
	c[totch++].val=y;
}
ll gcd(ll a,ll b){
	if(b==0) return a;
	return gcd(b,a%b);
}
int main(){
	fi;
	init();
	int T,op,x,y;
	ll p;
	sf("%d",&T);
	while(T--){
		sf("%d%d",&N,&m);
		totch=0;
		while(m--){
			sf("%d",&op);
			if (op==1){
				sf("%d%d%I64d",&x,&y,&p);
				sep(p);
				n=y;
				ll ans1=tot[y]-dfs(0,1);
				n=x-1;
				ll ans2=tot[x-1]-dfs(0,1);

				ll ans=ans1-ans2;
				fr(k,0,totch){
					if (c[k].pos<=y&&c[k].pos>=x){
						ll tmp=gcd(c[k].val,p);
						if (tmp==1) ans+=ll(c[k].val);
						ll tmp1=gcd(c[k].pos,p);
						if (tmp1==1) ans-=((ll)(c[k].pos));
					}
				}
				pf("%I64d\n",ans);
			}else{
				sf("%d%d",&x,&y);
				change(x,y);
			}
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值