HDU 4407 Sum(容斥)
2017-10-31 22:29
351 查看
题意:一个长度为n的序列(初始为1, 2, 3, ...n),现在q次操作,操作1:给你L,R, p, 求区间[L, R]中与p互质的数的和;
操作2:修改第x个数为c。(n <= 4e5, q <= 1e3)
思路:因为序列是1-n,所以区间求和可以利用容斥,因为q才1000,所以修改可以存起来,查询时暴力更新。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4e5+5;
int n, q, x, y, num, yz[maxn];
ll ans;
map<int, int> m;
void dfs(int cur, ll fac, int id)
{
ll tmp1, tmp2;
if(id%2)
{
ll n = y, d = fac;
ans -= (ll)(d+(n/d)*d)*(n/d)/2;
n = x-1;
ans += (ll)(d+(n/d)*d)*(n/d)/2;
}
else
{
ll n = y, d = fac;
ans += (ll)(d+(n/d)*d)*(n/d)/2;
n = x-1;
ans -= (ll)(d+(n/d)*d)*(n/d)/2;
}
for(int i = cur+1; i < num; i++)
dfs(i, fac*yz[i], id+1);
}
int main(void)
{
int _;
cin >> _;
while(_--)
{
m.clear();
scanf("%d%d", &n, &q);
while(q--)
{
int cmd, p, c;
scanf("%d%d", &cmd, &x);
if(cmd == 1)
{
scanf("%d%d", &y, &p);
num = 0;
int tt = p;
for(int i = 2; i*i <= tt; i++)
{
if(tt % i == 0)
{
yz[num++] = i;
while(tt % i == 0) tt /= i;
}
}
if(tt != 1) yz[num++] = tt;
ans = (ll)(x+y)*(y-x+1)/2;
for(int i = 0; i < num; i++)
dfs(i, yz[i], 1);
map<int, int>::iterator it;
for(it = m.begin(); it != m.end(); it++)
{
int fir = it->first;
int sec = it->second;
if(fir >= x && fir <= y)
{
if(__gcd(fir, p) == 1)
{
if(__gcd(sec, p) == 1) ans = ans-fir+sec;
else ans = ans-fir;
}
else
{
if(__gcd(sec, p) == 1) ans = ans+sec;
}
}
}
printf("%lld\n", ans);
}
else
{
scanf("%d", &c);
m[x] = c;
}
}
}
return 0;
}
操作2:修改第x个数为c。(n <= 4e5, q <= 1e3)
思路:因为序列是1-n,所以区间求和可以利用容斥,因为q才1000,所以修改可以存起来,查询时暴力更新。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4e5+5;
int n, q, x, y, num, yz[maxn];
ll ans;
map<int, int> m;
void dfs(int cur, ll fac, int id)
{
ll tmp1, tmp2;
if(id%2)
{
ll n = y, d = fac;
ans -= (ll)(d+(n/d)*d)*(n/d)/2;
n = x-1;
ans += (ll)(d+(n/d)*d)*(n/d)/2;
}
else
{
ll n = y, d = fac;
ans += (ll)(d+(n/d)*d)*(n/d)/2;
n = x-1;
ans -= (ll)(d+(n/d)*d)*(n/d)/2;
}
for(int i = cur+1; i < num; i++)
dfs(i, fac*yz[i], id+1);
}
int main(void)
{
int _;
cin >> _;
while(_--)
{
m.clear();
scanf("%d%d", &n, &q);
while(q--)
{
int cmd, p, c;
scanf("%d%d", &cmd, &x);
if(cmd == 1)
{
scanf("%d%d", &y, &p);
num = 0;
int tt = p;
for(int i = 2; i*i <= tt; i++)
{
if(tt % i == 0)
{
yz[num++] = i;
while(tt % i == 0) tt /= i;
}
}
if(tt != 1) yz[num++] = tt;
ans = (ll)(x+y)*(y-x+1)/2;
for(int i = 0; i < num; i++)
dfs(i, yz[i], 1);
map<int, int>::iterator it;
for(it = m.begin(); it != m.end(); it++)
{
int fir = it->first;
int sec = it->second;
if(fir >= x && fir <= y)
{
if(__gcd(fir, p) == 1)
{
if(__gcd(sec, p) == 1) ans = ans-fir+sec;
else ans = ans-fir;
}
else
{
if(__gcd(sec, p) == 1) ans = ans+sec;
}
}
}
printf("%lld\n", ans);
}
else
{
scanf("%d", &c);
m[x] = c;
}
}
}
return 0;
}
相关文章推荐
- hdu 4407 Sum(容斥)
- hdu 4407 Sum 容斥+当前离线
- hdu 4407 Sum(容斥)
- HDU 4407 Sum(容斥)
- 解题报告: HDU_4407 Sum 容斥+暴力
- HDU 4407 Sum【容斥原理】
- 容斥——HDU 4407
- hdu 4407 Sum (容斥原理)
- hdu 4407 Sum 容斥+离线
- hdu 4407 SUM
- HDU-4407-Sum(容斥原理)
- HDU-4407 Sum(容斥定理+伪离线处理)
- HDU 4407 Sum (容斥原理)
- [容斥原理] hdu 4407 Sum
- HDU-4407-Sum(容斥原理)
- hdu 4407 Sum(容斥原理)
- hdu 4407 Sum(容斥原理)
- HDU 4407 Sum 容斥原理
- hdu 4407 SUM(容斥原理)
- hdu 4407 sum