hdu 4407 Sum

题解:因为一开始的序列是1,2,3,...... n。而修改次数m最大为1000.对于每次询问可以先假设没有改变任何位置上的数。然后把改变的地方存到map中再暴力修改。

对于原来的1~n个数,可以预处理出每个p的质因子,然后运用容斥定理求解与p不互质的个数,用总数减去即可。

#include"bits/stdc++.h"
using namespace std;
#define fi first
#define se second
typedef long long LL;
const int MX = 4e5+7;
int n,m;
bool no_prime[MX];
int prime[MX][14],tt;
map<int,int> mp;

void get_prime()
{
    int n = 4e5;
    for(int i = 2; i <= n; i++){
        if(no_prime[i]) continue;
        prime[i][++prime[i][0]] = i;
        for(int j = i+i; j <= n; j+=i){
            no_prime[j] = 1;
            prime[j][++prime[j][0]] = i;
        }
    }
}

void dfs(LL &ans, int n,int p, int num, int cnt, int tail)
{
    if(tail == 0) return;
    int nxtnum = num*prime[p][tail];
    LL k = n/nxtnum;
    if(cnt&1) ans += nxtnum*k*(k+1)/2;
    else ans -= nxtnum*k*(k+1)/2;
    dfs(ans,n,p,num,cnt,tail-1);
    dfs(ans,n,p,nxtnum,cnt+1,tail-1);
}

LL work(int n,int p)
{
    LL ans = 0;
    dfs(ans,n,p,1,1,prime[p][0]);
    return ans;
}
void solve()
{
    scanf("%d%d",&n,&m);
    mp.clear();
    LL ret = 0;
    while(m--){
        int ty,x,y,p;
        scanf("%d%d%d",&ty,&x,&y);
        if(ty == 1){
            scanf("%d",&p);
            ret = ((LL)y*(y+1)/2 - (LL)x*(x-1)/2) - (work(y,p)-work(x-1,p));
            map<int,int> :: iterator it;
            for(it = mp.begin(); it != mp.end(); it++) if(x <= it->fi && it->fi <= y){
                if(__gcd(p,it->fi) == 1) ret -= it->fi;
                if(__gcd(p,it->se) == 1) ret += it->se;
            }
            cout<<ret<<endl;
        }
        else mp[x] = y;
    }
}
int main()
{
    int T;
    get_prime();
    for(scanf("%d",&T);T;T--) solve();
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值