题目连锁 :http://acm.hdu.edu.cn/showproblem.php?pid=4407
第一种操作 求x到y之间与p互质的数之和,容斥原理,求出不互质的数,减去就可以(remem)
第二种操作 把x改为y
#include<iostream> #include<cstring> #include<string> #include<cstdio> #include<stdio.h> #include<algorithm> #include<cmath> #include<set> #include<map> #include<queue> using namespace std; #define inf 0x3f3f3f3f #define eps 1e-9 #define mod 10007 #define FOR(i,s,t) for(int i = s; i < t; ++i ) #define REP(i,s,t) for( int i = s; i <= t; ++i ) #define LL unsigned long long #define ULL unsigned long long #define pii pair<int,int> #define MP make_pair #define lson id << 1 , l , m #define rson id << 1 | 1 , m + 1 , r #define maxn ( 400000+100 ) #define maxe ( 1000000+10 ) #define mxn 20000 bool isnot[maxn]; int prime[maxn], num; void get_prime() { //欧拉帅法 isnot[0] = isnot[1] = 1; for( int i = 2; i <= maxn; ++i ) { if( !isnot[i] ) prime[num++] = i; for( int j = 0; j < num && prime[j] * i < maxn; ++j ) { isnot[i*prime[j]] = 1; if( i % prime[j] == 0 ) break; } } } int p; int fac[maxn], cnt; void div( int x ) { //获取质因数 cnt = 0; for( int i = 0; prime[i] * prime[i] <= x; ++i ) { if( x % prime[i] == 0 ) { while( x % prime[i] == 0 ) x /= prime[i]; fac[cnt++] = prime[i]; } } if( x != 1 ) fac[cnt++] = x; } LL ans; void dfs ( int id, int c, LL num, int tot, int n ) { if( c == tot ) { LL k = n / num; if( c & 1 ) ans -= num * ( 1 + k ) * k / 2; else ans += num * ( 1 + k ) * k / 2; return ; } if( num > n || id >= cnt || c > tot ) return ; dfs ( id + 1, c, num, tot, n ); dfs ( id + 1, c + 1, num * fac[id], tot, n ); } LL solve( int n ) { ans = (LL)(1+n)*n/2; for( int i = 1; i <= cnt; ++i ) dfs( 0, 0, 1, i, n ); return ans; } map< int , int > mp; map<int , int > :: iterator it; int gcd( int a, int b ) { return b == 0 ? a : gcd( b, a%b ); } int main () { int T; //freopen( "in.in", "r", stdin ); get_prime(); scanf("%d", &T ); while( T-- ) { int n, m; scanf("%d%d", &n, &m ); mp.clear(); int op, x, y; while( m-- ) { scanf("%d", &op ); if ( op == 1 ) { scanf("%d%d%d", &x, &y, &p ); div( p ); LL res = solve( y ) - solve( x-1 ); for( it = mp.begin(); it != mp.end(); ++it ) { if( it->first < x || it->first > y ) continue; if( gcd( it->first, p ) == 1 ) res -= it->first; if( gcd( it->second, p ) == 1 ) res += it->second; } printf("%lld\n", res); } else { scanf("%d%d", &x, &y ); mp[x] = y; } } } }