題目鏈接:https://codeforc.es/contest/900/problem/D
題目大意:要你構造一個長度爲(未知)的數組,使得且,,輸出種類數。
思路:從,我們可以推斷出對於構造的數組,每個數都是的倍數,且所有數的和爲,由此可以聯想到類似於隔板法:將份至少分成兩份,最多分成份,不能爲空
這樣總的分類數即爲:令爲份數,
但是我們注意到單純這樣分是存在問題的,例如:,我們可能會分出這樣錯誤的情況,所以我們需要去除掉不合法的種類數,我們可以發現:不合法的種類數產生的原因爲:份數爲的因子,所以我們減掉份數爲的因子的值就了。
AC代碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll qpow(ll x,ll y){
ll ans=1;
while(y){
if(y&1){
ans=ans*x%mod;
}
x=x*x%mod;
y>>=1;
}
return ans;
}
map<ll ,ll >mp;
ll dfs(ll x){
if(mp[x]){
return mp[x];//用map映射直接返回,減少多餘計算
}
if(x==1){
return 1;
}
mp[x]=(qpow(2,x-1)-1+mod)%mod;
for(ll i=2;i*i<=x;i++){
if(x%i==0){
mp[x]=(mp[x]-dfs(x/i)+mod)%mod;
if(i*i!=x){
mp[x]=(mp[x]-dfs(i)+mod)%mod;
}
}
}
return mp[x];
}
int main()
{
ll x,y;
cin>>x>>y;
if(y%x!=0){//序列總和不是gcd的倍數
cout<<0<<endl;
}
else{
ll cnt=y/x;
ll ans=dfs(cnt);
cout<<ans<<endl;
}
return 0;
}