标签:
input | output |
---|---|
3 6 |
4 |
大致题意:
输入 a n 判断 从 b = 1 ~ n 中 满足 gcd( ( a * a + b * b ) , 4 * a + 4 * b ) > 1 的个数。
a < 1e12 , n < 1e18
若 a b 奇偶性相同,显然满足。gcd是2的倍数。
若a b 奇偶性不同,
开始推导:
因为 a * a + b * b 是奇数,
所以
gcd( a * a + b * b , 4 * a + 4 * b ) > 1 等价于
gcd( a * a + b * b , a + b ) > 1 等价于
根据整除性质,若存在 e > 1 ,满足 e | ( a + b ) , 那么 e | ( a + b ) ^ 2 反之亦然
则等价于
gcd( a * a + b * b , a * a + b * b + 2 * a * b ) > 1 等价于
gcd( 2 * a * a + 2 * b * b , a * a + b * b + 2 * a * b ) > 1等价于
gcd( a * a + b * b - 2 * a * b , a * a + b * b + 2 * a * b ) > 1 等价于
gcd( a - b , a + b ) > 1 等价于
gcd( 2 * a , a + b ) > 1
因为 a+b是奇数
等价于
gcd( a , a +b ) > 1等价于
gcd( a , b ) > 1
推导结束
下面对a分解质因数,找出n个数中不同奇偶性且满足gcd( a , b ) > 1的个数
最后加上 相同奇偶性的 个数 就是答案。
所以要求1~maxn中与a,gcd > 1 的个数,就是求1~maxn与某一个num不互素的个数,要用到容斥原理:
ll no_coprime(ll num,ll MAXN){//1~maxn与num不互素的个数 ll ans = 0; vector<ll> fac; for(ll i = 2; i*i <= num; i++){ //分解因数 if( num % i == 0){ fac.push_back(i); while(num%i == 0) num /= i; } } if(num != 1) fac.push_back(num); int sz = SZ(fac); for(ll mask = 1 ; mask < (1LL<<sz); mask++){ //容斥过程,复杂度2^因数个数 ll c = 0; ll tmp = 1; rep(i,sz) if( (1LL<<i)&mask){ c++; tmp *= fac[i]; } if(c&1) ans += MAXN/tmp; else ans -= MAXN/tmp; } return ans; }
ac代码:
//Accepted 412 15 G++ 4.9 C++11 2092 //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <cstdio> #include <ctime> #include <bitset> #include <algorithm> #define SZ(x) ((int)(x).size()) #define ALL(v) (v).begin(), (v).end() #define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i) #define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i) #define REP(i,n) for ( int i=1; i<=int(n); i++ ) #define rep(i,n) for ( int i=0; i<int(n); i++ ) using namespace std; typedef long long ll; #define X first #define Y second typedef pair<ll,ll> pii; template <class T> inline bool RD(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void PT(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) pt(x / 10); putchar(x % 10 + '0'); } ll a,n; ll no_coprime(ll num,ll MAXN){ ll ans = 0; vector<ll> fac; for(ll i = 2; i*i <= num; i++){ //分解因数 if( num % i == 0){ fac.push_back(i); while(num%i == 0) num /= i; } } if(num != 1) fac.push_back(num); int sz = SZ(fac); for(ll mask = 1 ; mask < (1LL<<sz); mask++){ //容斥过程,复杂度2^因数个数 ll c = 0; ll tmp = 1; rep(i,sz) if( (1LL<<i)&mask){ c++; tmp *= fac[i]; } if(c&1) ans += MAXN/tmp; else ans -= MAXN/tmp; } return ans; } int main(){ while(cin>>a>>n){ ll ans = 0; if(a&1) ans += (n+1)/2, n /= 2; ans += no_coprime(a,n); printf("%lld\n",ans); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
URAL 1907. Coffee and Buns(数论推导+容斥原理)
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/47306257