题目链接:https://ac.nowcoder.com/acm/contest/883/D
题目大意:定义f(n)=n个1组成的十进制数,如f(3)=111,给出n和m,求1~n中取i,1~m中取j,有几对
题目思路:首先当p为2和5的时候可以发现无论如何它都没法mod p得到0,所以直接输出0就好。
为书写方便,这里定义
所以原式等价于求
在p为3的情况下,由于3和9不互质,9没有逆元,所以3需要另外算,3的倍数就是所有位上的和需要是3的倍数,由于本题每一位都是3,所以就是求是3的倍数的种类数,那就要求i是3的倍数,这种i共有n/3种,每种都可以跟任意一个j合作符合要求,也就是n/3*m
其他情况继续讨论,由于inv(9)不等于0
所以
2和5已经刚才讨论过,剩下的全是跟10互质的p
那么由费马小定理or欧拉定理均可以得知
也就是循环节最大也就p-1了,如果想变小的话,很明显得要是它的因数,所以直接sqrt(n)枚举因数看看最小的循环节是谁。
找到最小循环节以后,假设它是x,那么它分解质因数以后得到的会是
对于最小的质数2,当指数为30时就已经超过了1e9,所以a不会大于30,如果大于的话直接当30算就行,因为只要temp拥有x的每一个质因子且数量大于等于x的相应数量就行。
所以对于每个j来说,最小的那个符合要求的数字得拥有x的每一个质因子且数量大于等于x的相应数量,直接a1/j向上取整就行,然后找出n里有多少个这种符合要求的数字的倍数,本题就结束了
以下是代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(ll i=a;i<=b;i++)
#define per(i,a,b) for(ll i=a;i>=b;i--)
#define ll long long
const ll MAXN = 5e5+5;
const ll MOD = 1e9+7;
ll powmod(ll x,ll y,ll MOD){
ll rst=1;
for(;y;y>>=1){
if(y&1)rst=rst*x%MOD;
x=x*x%MOD;
}
return rst;
}
ll a[MAXN],num[MAXN];
int main()
{
ll t,p,n,m;
scanf("%lld",&t);
while(t--){
memset(num,0,sizeof(num));
scanf("%lld%lld%lld",&p,&n,&m);
if(p==2||p==5){cout<<0<<endl;continue;}
if(p==3){cout<<n/3*m<<endl;continue;}
ll temp=p-1,anss=p-1,pos=0;
for(ll i=2;i<=sqrt(temp);i++){
if(temp%i==0){
if(powmod(10,i,p)==1){
anss=min(anss,i);
}
if(powmod(10,temp/i,p)==1){
anss=min(anss,temp/i);
}
}
}
rep(i,2,sqrt(anss)){
if(anss%i==0){
a[++pos]=i;
while(anss%i==0)num[pos]++,anss/=i;
}
}
if(anss!=1){
a[++pos]=anss;
num[pos]=1;
}
ll ans=0;
rep(j,1,min(30ll,m)){
ll rst=1;
rep(i,1,pos){
rst*=powmod(a[i],ceil(1.0*num[i]/j),p);
}
ans+=n/rst;
if(j==30)ans+=n/rst*(m-30);
}
printf("%lld\n",ans);
}
return 0;
}