HDU--4407(容斥原理)
2015-05-14 19:24:05
题目:给出一列数(1~n),然后有 m(m<=1000)个询问,每个询问有两种,(1)查询区间 [a,b] 中与 p 互素的数的和,(2)改第 x 个数为 c
总结:注意到 m 很小,所以直接对于每个查询,先用容斥处理,然后重新暴力处理之前的所有更改即可,上界:1000*1000。
有个细节:如何一个点被更改多次,我们只用算最后一次的更改,可以用 map 来实现。(我的话比较傻X地标记已经处理过的位置)
map实现:
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB(a) push_back(a) typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; const int MAXN = 1000; int fact[MAXN],fcnt; int T,n,m; ll res; map<int,int> mp; map<int,int>::iterator it; void Dfs(int top,int p,int v,int cnt){ if(p > fcnt){ if(cnt == 0) return; int num = top / v; ll cur = (ll)(num+1)*num/2*v; if(cnt & 1) res += cur; else res -= cur; return; } Dfs(top,p + 1,v,cnt); Dfs(top,p + 1,v * fact[p],cnt + 1); } int Gcd(int a,int b){ while(a > 0 && b > 0) if(a > b) a %= b; else b %= a; return a + b; } int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); mp.clear(); while(m--){ int op,a,b,c; ll ans = 0; scanf("%d",&op); if(op == 1){ scanf("%d%d%d",&a,&b,&c); fcnt = 0; int tc = c; for(int i = 2; i * i <= c; ++i) if(tc % i == 0){ fact[++fcnt] = i; while(tc % i == 0) tc /= i; } if(tc != 1) fact[++fcnt] = tc; res = 0; Dfs(a - 1,1,1,0); ans -= (ll)a*(a-1)/2 - res; res = 0; Dfs(b,1,1,0); ans += (ll)(b+1)*b/2 - res; for(it = mp.begin(); it != mp.end(); it++){ int v1 = (*it).first,v2 = (*it).second; if(v1 < a || v1 > b) continue; if(Gcd(v1,c) == 1) ans -= v1; if(Gcd(v2,c) == 1) ans += v2; } printf("%I64d\n",ans); } else{ scanf("%d%d",&a,&c); mp[a] = c; } } } return 0; }
标记位置:
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB(a) push_back(a) typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; const int MAXN = 1000; int fact[MAXN],fcnt; int T,n,m; int q[1010][2],qcnt; ll res; bool vis[400010]; void Dfs(int top,int p,int v,int cnt){ if(p > fcnt){ if(cnt == 0) return; int num = top / v; ll cur = (ll)(num+1)*num/2*v; //printf("v,cnt,num,cur:%d %d %d %d\n",v,cnt,num,cur); //printf("cur : %lld\n",cur); if(cnt & 1) res += cur; else res -= cur; return; //printf("res : %lld\n",res); } Dfs(top,p + 1,v,cnt); Dfs(top,p + 1,v * fact[p],cnt + 1); } int Gcd(int a,int b){ while(a > 0 && b > 0) if(a > b) a %= b; else b %= a; return a + b; } int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); qcnt = 0; while(m--){ int op,a,b,c; ll ans = 0; scanf("%d",&op); if(op == 1){ scanf("%d%d%d",&a,&b,&c); fcnt = 0; int tc = c; for(int i = 2; i * i <= c; ++i) if(tc % i == 0){ fact[++fcnt] = i; while(tc % i == 0) tc /= i; } if(tc != 1) fact[++fcnt] = tc; res = 0; Dfs(a - 1,1,1,0); ans -= (ll)a*(a-1)/2 - res; res = 0; Dfs(b,1,1,0); ans += (ll)(b+1)*b/2 - res; memset(vis,0,sizeof(vis)); for(int i = qcnt; i >= 1; --i){ if(vis[q[i][0]] || q[i][0] < a || q[i][0] > b) continue; vis[q[i][0]] = 1; if(Gcd(q[i][0],c) == 1) ans -= q[i][0]; if(Gcd(q[i][1],c) == 1) ans += q[i][1]; } printf("%I64d\n",ans); } else{ scanf("%d%d",&a,&c); q[++qcnt][0] = a; q[qcnt][1] = c; } } } return 0; }