算法:
利用数据1...N的性质,求与P的互质的个数,位运算,容斥定理。。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> #include<vector> #include<string> #include<math.h> #include<map> #include<set> #include<algorithm> using namespace std; struct info { int s,e,p,num; }seg[1010]; struct pinfo { int id, v, num; }p[1010]; int factor[1000]; //保存因子 map<int,int>mp; int gcd( int n, int m ) { return m ? gcd(m, n % m ) : n; } //容斥定理求互质之和 long long cal( int x, int n) { //分解出x的因子 if( x == 0 ) return 0; int i,Lim = sqrt( x * 1.0 ), cnt = 0; for( i = 2; i <= Lim; i++) { if( x % i == 0 ) { factor[++cnt] = i; while( x % i == 0 ) x = x / i; } } if( x != 1 ) { factor[++cnt] = x; } int mask = 1 << cnt; long long ans = 0; for( int i = 1; i < mask; i++) { int tt = 0, fac = 1, k; for( int j = 0; j < cnt; j++) { if( i & (1<<j) ) { tt++; fac *= factor[j+1]; } } //如果是奇数项 if( tt & 1 ) { k = n / fac; ans += ( fac + 1LL * fac * k ) * k / 2; } else { k = n / fac; ans -= ( fac + 1LL * fac * k ) * k / 2; } } return ans; } int main( ) { int N, M, a, b, c, d, c1, c2, T; scanf("%d",&T); while( T-- ) { scanf("%d%d",&N,&M); c1 = c2 = 0; for( int i = 1; i <= M; i++) { scanf("%d",&a); if( a == 1 ) { scanf("%d%d%d",&seg[c1].s, &seg[c1].e, &seg[c1].p); seg[c1].num = i; c1++; } else { scanf("%d%d",&p[c2].id, &p[c2].v); p[c2].num = i; c2++; } } long long x, y, pans; for( int i = 0; i < c1; i++) //枚举每一个查询 { x = cal(seg[i].p, seg[i].s-1); y = cal(seg[i].p, seg[i].e); pans = ((1 + seg[i].e * 1LL) * seg[i].e * 1LL / 2 - y ) - (1 + seg[i].s - 1 ) * 1LL * (seg[i].s - 1) * 1LL / 2 + x; mp.clear(); for( int j = 0; j < c2; j++) { if( p[j].num < seg[i].num && seg[i].e >= p[j].id && seg[i].s <= p[j].id ) { mp[p[j].id] = p[j].v; } else if( p[j].num > seg[i].num ) break; } map<int,int>::iterator it; for( it = mp.begin(); it != mp.end(); it++) { int xx = gcd(seg[i].p, it->second); int yy = gcd(seg[i].p, it->first); if( yy == 1 && xx != 1 ) pans -= it->first; else if( yy != 1 && xx == 1 ) pans += it->second; else if( yy == 1 && xx == 1 ) pans += it->second - it->first; } printf("%I64d\n", pans); } } return 0; }