內個……我還沒有計蒜客的賬號,就先不給題目傳送門了……
看到數據範圍不正常,就想到了數位DP。
定義
當我們已知
附上AC代碼:
#include <cstdio>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int t,mod,p[N],miu[N],num,len,a[70];
ll f[70][N],l,r;
bool b[N];
inline void get(int n){
miu[1]=1;
for (int i=2; i<=n; ++i){
if (!b[i]) p[++num]=i,miu[i]=-1;
for (int j=1; j<=num&&p[j]*i<=n; ++j){
b[p[j]*i]=1,miu[p[j]*i]=-miu[i];
if (i%p[j]==0) {miu[p[j]*i]=0;break;}
}
}
return;
}
inline void change(ll x){
len=0;do a[++len]=x%mod,x/=mod; while (x);
return;
}
inline int gcd(int a,int b){return !b?a:gcd(b,a%b);}
inline ll so(int x,int pre,bool b){
if (x==1) return 1ll;
if (!b&&f[x][pre]) return f[x][pre];
ll ans=0,lim=b?a[x-1]:mod-1;
for (int i=1; i<=lim; ++i) if (gcd(pre,i)==1) ans+=so(x-1,i,b&&(i==lim));
if (!b) f[x][pre]=ans;
return ans;
}
inline ll calc(ll x){
change(x);ll ans=0;
for (int i=1; i<len; ++i) for (int j=1; j<mod; ++j) ans+=f[i][j];
for (int i=1; i<=a[len]; ++i) ans+=so(len,i,i==a[len]);
return ans;
}
int main(void){
for (get(1e5),scanf("%d",&t); t; --t){
scanf("%lld%lld%d",&l,&r,&mod),change(r);
for (int i=0; i<=len; ++i) for (int j=0; j<mod; ++j) f[i][j]=0;
for (int i=1; i<mod; ++i) f[1][i]=1;
for (int i=2; i<=len; ++i)
for (int d=1; d<mod; ++d){
ll sum=0;
for (int t=d; t<mod; t+=d) sum+=f[i-1][t];
for (int t=d; t<mod; t+=d) f[i][t]+=sum*miu[d];
}
printf("%lld\n",calc(r)-calc(l-1));
}
return 0;
}