题意:
已知序列A为1,11,111,1111,... 1,11,111,1111,...1,11,111,1111,...,求
思路:
,那么有
考虑 和p的关系,先考虑9和p互质
那么可以变为
由于互质 inv9≠0
所以只有
即
根据费马小定理,10 和p 互质有
由于 ,那么循环节至少为p−1,考虑是否有更小的循环节,根据同余式的性质
那么令d 为p−1 的因子,即d∣p−1,最小的循环节可能为d
所以我们可以对p−1的因子进行检验得到最小的循环节d ,找到了最小的循环节d 之后我们如何求解答案呢。由于循环节为d,所以 ,必须是d的倍数。考虑j是固定的,那么只要i含有的因子就可以了,令 ,那么1∼n中是g的倍数的个数为 。再考虑g,我们可以将d 唯一分解了,
那么就有
g就有
随着j的变化,g的值也是变化的,设 ,当j的值为 时g也就是随着变化的,我们分别计算每一个的贡献为 ,当j>maxn时g将不再变化贡献就为
这样就能统计出答案了,但是当p=2,p=5时,虽然,9和p互质但是是 ,所以明显的答案都为0 第二我们考虑p=3 的情况,由于p=3 于分母9 并不互质,所以我们并不能像上面那么做。考虑
由于为长度为连续的1的整数,一个整数是否能被3整除我们知道就是把各位上的数字加起来是3的倍数就能整除了,令A(i)每一位上的和为S,那么每一位上的和就为,j由于A 上的每一位都是1,所以S=i ,故最后的答案就是n/3∗m
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
ll power(ll a,ll b,ll mod)
{
ll ans=1;
while(b)
{
if(b&1)
ans=(ans*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return ans%mod;
}
ll powerr(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
ans=ans*a;
b>>=1;
a=a*a;
}
return ans;
}
pair<int,int>a[1005];
int main()
{
int t;
cin>>t;
while(t--)
{
ll p,n,m;
cin>>p>>n>>m;
if(p==2||p==5)
{
cout<<0<<endl;
continue;
}
if(p==3)
{
cout<<n/3*m<<endl;
continue;
}
int minn=p-1;
ll x=minn;
for(int i=2;i*i<=x;i++)//找D的循环节
{
if(x%i==0)
{
if(power(10,i,p)==1)
minn=min(minn,i);
if(power(10,x/i,p)==1)
minn=min(1ll*minn,x/i);
}
}
int cnt=0;
int maxn=0;
x=minn;
for(int i=2;i*i<=x;i++)// 将D进行质因数分解
{
if(x%i==0)
{
a[cnt].second=0;
a[cnt].first=i;
while(x%i==0)
{
a[cnt].second++;
x/=i;
}
maxn=max(maxn,a[cnt].second);
cnt++;
}
}
if(x>1)
{
a[cnt].first=0;
a[cnt].second=0;
a[cnt].first=x;
a[cnt].second++;
maxn=max(maxn,a[cnt].second);
cnt++;
}
ll ans=0;
ll g=1;
for(int j=1;j<=min(1ll*maxn,m);j++)// 每次找到最小的g a[cnt].first/j的向上取整
{
g=1;
for(int i=0;i<cnt;i++)
{
ll flag=a[i].second/j;
if(a[i].second%j)
flag++;
g=g*powerr(a[i].first,flag);
}
ans=ans+n/g;// 1~n 中有n/g个合法的i
}
if(m>maxn)
{
ans=ans+n/g*(m-maxn);// m的值大于最大的指数 直接计算即可
}
cout<<ans<<endl;
}
return 0;
}