对于每个正整数 nn,我们定义它的 pp 进制表示 由 mm 个非负整数 a_1, a_2, \cdots, a_ma?1??,a?2??,?,a?m?? 组成,并且这些数字满足 \displaystyle n = \sum_{i = 1}^{m}{a_i p^{i - 1}}n=?i=1?∑?m??a?i??p?i−1??,以及 0 \leq a_i < p\ (i = 1, 2, \cdots, m - 1)0≤a?i??<p (i=1,2,?,m−1) 和 1 \leq a_m < p1≤a?m??<p。
在阿里云台上,用户登录的秘钥都是由一个正整数组成。一个可被用作秘钥的正整数 nn,它的 pp 进制表示需要满足 1 \leq a_i < p\ (i = 1, 2, \cdots, m)1≤a?i??<p (i=1,2,?,m) 且 \gcd(a_i, a_{i + 1}) = 1\ (i = 1, 2, \cdots, m - 1)gcd(a?i??,a?i+1??)=1 (i=1,2,?,m−1)。比如当 p = 10p=10 时,6161 是一个合法秘钥,32163216 也是;但是当 p = 100p=100 时,6161 依旧是一个合法秘钥,32163216 却不是。
给出正整数 L, RL,R 和 pp,请你统计满足 L \leq n \leq RL≤n≤R 并且 nn 是一个合法秘钥的正整数 nn 的数量。
输入格式
第一行包含一个正整数 T(1 \leq T \leq 10^3)T(1≤T≤10?3??),表示有 TT 组测试数据。
接下来依次给出每组测试数据,每组测试数据仅一行,包含三个正整数 L, R(1 \leq L \leq R \leq 10^{18})L,R(1≤L≤R≤10?18??) 和 p(2 \leq p \leq 10^5)p(2≤p≤10?5??) ,含义见题目描述。
保证不超过 5050 组数据满足 p > 10^3p>10?3??。
输出格式
对于每组数据输出一行,包含一个整数,表示满足条件的数字数量。
样例输入
4 5 7 9 1 100 2 1 100 5 2017 2121 10
样例输出
3 6 41 10分析:考虑第一次最高位比原数小的,后面的信息可以直接用莫比乌斯得到; 这样依次按位枚举即可;代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <bitset> #include <map> #include <queue> #include <stack> #include <vector> #include <cassert> #include <ctime> #define rep(i,m,n) for(i=m;i<=(int)n;i++) #define mod 1000000007 #define inf 0x3f3f3f3f #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define sys system("pause") #define ls rt<<1 #define rs rt<<1|1 #define all(x) x.begin(),x.end() const int maxn=1e5+10; const int N=2e2+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;} int n,m,k,t,p[maxn],mo[maxn],phi[maxn],cnt,num[20]; bool vis[maxn]; vector<ll>ret[maxn],sum[maxn]; void init() { mo[1]=1; phi[1]=1; for(int i=2;i<=maxn-10;i++) { if(!vis[i]) { mo[i]=-1; phi[i]=i-1; p[cnt++]=i; } for(int j=0;j<cnt&&(ll)i*p[j]<=maxn-10;j++) { vis[i*p[j]]=true; if(i%p[j]==0) { mo[i*p[j]]=0; phi[i*p[j]]=phi[i]*p[j]; break; } mo[i*p[j]]=-mo[i]; phi[i*p[j]]=phi[i]*(p[j]-1); } } } void build(int len,int bs) { int i,j,k; rep(i,0,len)ret[i].resize(bs),sum[i].resize(bs); rep(i,1,bs-1)ret[1][i]=1,sum[1][i]=0; rep(i,1,bs-1) { for(j=i;j<bs;j+=i)sum[1][i]+=ret[1][j]; } rep(i,2,len) { for(j=1;j<bs;j++)ret[i][j]=0,sum[i][j]=0; for(j=1;j<bs;j++) { for(k=j;k<bs;k+=j) { ret[i][k]+=mo[j]*sum[i-1][j]; } } for(j=1;j<bs;j++) { for(k=j;k<bs;k+=j) { sum[i][j]+=ret[i][k]; } } } } ll gao(ll x,int bs,int tp) { int pos=0; while(x)num[++pos]=x%bs,x/=bs; if(tp)build(pos,bs); ll ans=0; int i,j; rep(i,1,pos-1)rep(j,1,bs-1)ans+=ret[i][j]; for(i=pos;i>=1;i--) { for(j=1;j<num[i];j++) { if(i==pos||__gcd(num[i+1],j)==1)ans+=ret[i][j]; } if(num[i]==0||(i!=pos&&__gcd(num[i],num[i+1])!=1))break; } return ans; } int main() { int i,j; init(); scanf("%d",&t); while(t--) { ll p,q; scanf("%lld%lld%d",&p,&q,&m); printf("%lld\n",gao(q+1,m,1)-gao(p,m,0)); } return 0; }