1. 程式人生 > >積性函式 hdu5528 Count a * b

積性函式 hdu5528 Count a * b

積性函式太有趣了!
做這個題之前,我們需要掌握一些基本知識。

1.若f(x)為積性函式,那麼滿足f(xy)=f(x)f(y)
2.若f(x)為積性函式,g(x)=d|xf(d),那麼g(x)也為積性函式
3.學會如何線性處理積性函式。
4.對於積性函式,目標就是學會如何求f(pq),p為質數

回到這個題,我們先考慮求f函式
f(m)=m1a=0m1b=0[gcd(m,ab)!=m]
我們考慮a b的所有組合,一共m2情況
考慮f函式的反面,即f(x)=m1a=0m1b=0[gcd(m,ab)==m]
gcd(m,a)=d,那麼如果滿足gcd

(m,ab)=m,必有md|b
滿足gcd(m,a)=d的a個數為φ(md)
在上面情況滿足下且滿足md|b,b的個數為d
得到f(m)=m2d|mdφ(d)
能發現前者和後者都是積性函式,拆成2部分記為f1,f2
然後g函式也拆成2部分,記為g1,g2
因為我們知道g1和g2是積性的,所以很容易打表就能找到規律(QAQ太弱了,推不出來,只能打表)
得到
g1(pq)=g1(pq1)p2+1
g2(pq)=(q+1)pq
這題就做完啦

#include <map>
#include <set>
#include <list>
#include <cmath> #include <ctime> #include <stack> #include <queue> #include <cstdio> #include <memory> #include <cctype> #include <bitset> #include <string> #include <vector> #include <cassert> #include <climits> #include <cstring>
#include <iomanip> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define fuck(x) std::cout << "[" << x << "]"; #define FIN freopen("input.txt", "r", stdin); #define FOUT freopen("output.txt", "w+", stdout); typedef long long ll; typedef long double ldb; typedef std::pair<ll, int> pli; typedef std::pair<int, int> pii; typedef unsigned long long ull; typedef std::pair<double, double> pdd; const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; const int mod = 1e9 + 7; const int MX = 4e4 + 5; int prime[MX], psz; bool not_prime[MX]; void prepare() { not_prime[1] = true; for(int i = 2; i < MX; i++) { if(!not_prime[i]) { prime[++psz] = i; } for(int j = 1; j <= psz && (ll)i * prime[j] < MX; j++) { int x = i * prime[j]; not_prime[x] = true; if(i % prime[j] == 0) break; } } } ull solve(int n) { ull g1 = 1, g2 = 1; for(int i = 1; i <= psz && (ll)prime[i]*prime[i] <= n; i++) { if(n % prime[i] == 0) { int p = prime[i], q = 0; while(n % prime[i] == 0) { q++; n /= prime[i]; } ull f1 = 1, f2 = q + 1; for(int j = 1; j <= q; j++) { f1 = f1 * p * p + 1; f2 = f2 * p; } g1 *= f1; g2 *= f2; } } if(n != 1) { int p = n; g1 *= (ull)p * p + 1; g2 *= 2 * p; } return g1 - g2; } int main() { // FIN; prepare(); int T; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); printf("%llu\n", solve(n)); } return 0; }