題目傳送門
題意:
正整數序列 ,序列的 是 ,並且序列之和是 。
問這樣的序列個數,答案取模。
數據範圍: 。
題解:
容易發現存在這樣的序列等價於 。
簡化一下題意,這樣的序列是 是 ,並且序列之和是 。
是 ,並且序列之和是 的函數 是不好求的。
序列之和是 的函數 是很好求的。
這樣就考慮莫比烏斯反演了。
想一想會發現, 。
反演一下, 。
通過插板法可以知道 。
感受:
容斥題,可以考慮莫比烏斯反演。
代碼:
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const ll mod = 1e9 + 7 ;
ll qpow(ll a , ll b)
{
ll ans = 1 ;
a %= mod ;
while(b)
{
if(b & 1) ans = (ans * a) % mod ;
b >>= 1 , a = (a * a) % mod ;
}
return ans % mod ;
}
ll get_mu(ll n)
{
ll x = n , temp = n ;
ll cnt = 0 , now = 0 ;
for(ll i = 2 ; i * i <= x ; i ++)
{
now = 0 ;
if(x % i == 0)
{
while(x % i == 0) now ++ , x /= i ;
if(now > 1) return 0 ;
cnt ++ ;
}
}
if(x != 1) cnt ++ ;
return (cnt & 1) ? -1 : 1 ;
}
ll g(ll x)
{
return qpow(2ll , x - 1) ;
}
void solve(ll x)
{
ll ans = 0 ;
for(ll d = 1 ; d * d <= x ; d ++)
{
if(x % d != 0) continue ;
ans += get_mu(d) * g(x / d) ;
if(d * d != x)
ans += get_mu(x / d) * g(d) ;
ans %= mod ;
}
ans = (ans + mod) % mod ;
printf("%lld\n" , ans) ;
}
int main()
{
ll x , y ;
scanf("%lld%lld" , &x , &y) ;
if(y % x != 0){printf("0\n") ; return 0 ;}
solve(y / x) ;
return 0 ;
}