hdu 4407 Sum(容斥原理)
2017-08-26 11:50
381 查看
先给n个数,1-n,排成一行,进行m次操作。操作1是计算第x个数和第y个数(闭区间)之间和p互质的数字的和。操作2是把第x个数字改成c。如果没有第二个操作,这个题还是很简单的,看到第二个操作,就有点懵了,一旦修改了数字那就不是连续的了,不好求了。好在修改次数很少,顶多1000次操作,只有一部分是操作2.这样就可以把操作2用一个map记录下来,然后按照连续区间求和,然后再遍历map修改那些改变过的值。
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int MAXN = 400100; map<int,int> mp; LL prime[65]; LL plen = 0; LL getSum(LL n) { return n*(n+1)/2; } LL solve(LL R, LL L, int p) { plen = 0; int pp = p; for(int i = 2; i <= pp/i; ++i) { if(pp%i == 0) { prime[plen++] = i; while(pp%i == 0) pp /= i; } } if(pp > 1) prime[plen++] = pp; LL res = 0; for(LL i = 1; i < (1LL << plen); ++i) { LL mult = 1; LL cnt = 0; for(int j = 0; j < plen; ++j) { if(i&(1<<j)) { mult *= prime[j]; ++cnt; } } if(cnt&1) res += mult*(getSum(R/mult)-getSum(L/mult)); else res -= mult*(getSum(R/mult)-getSum(L/mult)); } LL allSum = getSum(R)-getSum(L); for(pair<int,int> pa : mp) { if(pa.first <= L) continue; if(pa.first > R) break; allSum -= pa.first; allSum += pa.second; if(__gcd(pa.first,p) != 1 && __gcd(pa.second,p) != 1) { res -= pa.first; res += pa.second; } else if(__gcd(pa.first,p) != 1 && __gcd(pa.second,p) == 1) res -= pa.first; else if(__gcd(pa.first,p) == 1 && __gcd(pa.second,p) != 1) res += pa.second; } return allSum - res; } int main() { int T,m,n,op; scanf("%d",&T); int x,y,p,c; while(T--) { mp.clear(); scanf("%d %d",&n,&m); while(m--) { scanf("%d",&op); if(op == 2) { scanf("%d %d",&x,&c); mp[x] = c; continue; } scanf("%d %d %d",&x,&y,&p); printf("%I64d\n",solve(y,x-1,p)); } } return 0; }
相关文章推荐
- HDU 4407 sum 容斥原理
- HDU 4407 Sum(容斥原理)
- HDU-4407-Sum(容斥原理)
- HDU 4407 Sum(容斥原理)
- HDU 4407 Sum(12年金华 容斥原理)
- [容斥原理] 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 <容斥原理>
- hdu 4407 Sum 容斥原理
- HDU 4407 Sum 容斥原理