【莫比乌斯反演】牛客练习赛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;
}
}
发表评论