【莫比乌斯反演】牛客练习赛40E-小D的lemon

本题细节极多。WA题自闭两开花

传送门

解题方法打字太难了。手写算了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 250025;
ll p = 1e9 + 7;
ll primes[maxn], mu[maxn], g[maxn], f[maxn], invg[maxn], inv[maxn], s[maxn], cnt;
bool st[maxn];
ll ksm(ll n, ll m)
{
    ll res = 1;
    while(m)
    {
        if(m & 1LL) res = (res * n) % p;
        n = (n * n) % p;
        m >>= 1LL;
    }
    return res;
}
void get_primes(int n)
{
    mu[1] = 1; f[1] = 1; invg[1] = 1; s[0] = s[1] = 1,g[1] = 1;
    for(int i = 2; i <= n; i++)
    {
        f[i] = 1;
        if(!st[i]) 
        {
            primes[++cnt] = i;
            mu[i] = -1;
            g[i] = 1;
        }
        invg[i] = ksm(g[i], p - 2);
        for(int j = 1; j <= cnt && i * primes[j] <= n; j++)
        {
            st[i * primes[j]] = true;
            g[primes[j] * i] = g[i] + 1;
            if(i % primes[j] == 0)
            {
                mu[primes[j] * i] = 0;
                break;
            }
            mu[primes[j]  * i] = -mu[i];
        }
    }
    for(int i = 1; i <= n; i++)
    {
        if(mu[i] != 0)  
        for(int j = i; j <= n; j += i)
        {    
            ll tb = (mu[i] == 1) ? g[j / i] : invg[j / i];
            f[j] = f[j] * tb % p;   
        }
    }
    inv[0] = 1;
    for(int i = 1; i <= n; i++)
    {
        s[i] = f[i] * s[i - 1] % p;
        inv[i] = ksm(s[i], p - 2);
    }
}
int main()
{
    int t;
    get_primes(maxn - 25);
    //for(int i = 1; i <= 5; i++ )cout<<f[i] << " ";
    //cout<<endl;
    cin >> t;
    while(t--)
    {
        ll a,b;
        cin >> a >> b;
        if(a > b) swap(a,b);
        ll c = 0, ans = 1;
        for(ll i = 1; i <= a; i = c + 1)
        {
            c = min(a / (a / i), b / (b / i));
            ll tk = (a / i) * (b / i) % (p - 1);
            ll tn = s[c] * inv[i - 1] % p;
            //cout << tk << " " << tn << endl;
            ans = ans * ksm(tn, tk) % p;
        }
        cout << ans << endl;
    }

}

发表评论

邮箱地址不会被公开。 必填项已用*标注