搞不懂为什么理论复杂度那么大。。但是的确跑不满。。。
根据题意,得到
g ∣ 1 0 d c + d b b ′ + 1 0 d c a ′ g|\frac {10^{dc+db}} {b'}+\frac {10^{dc}} {a'} g∣b′10dc+db+a′10dc
其中 g = ( a , b ) , a ′ = a / g , b ′ = b / g g=(a,b),a'=a/g,b'=b/g g=(a,b),a′=a/g,b′=b/g
然后,由于 ( a ′ , b ′ ) = 1 (a',b')=1 (a′,b′)=1,所以这两项都必须是整数,换言之, a ′ , b ′ a',b' a′,b′的质因子只有2,5,且它们互质
然后。。就很暴力了。。。直接爆枚dc,db,a’,b’,对每个得到的数,直接暴力算出其每个因子,然后check。。。
枚举因子为了节省时间必须用pollard rho。。。
然后就可以卡过去了。。。没错理论复杂度 O ( X l o g 2 N l g 2 N ) O(\sqrt X log^2Nlg^2N) O(Xlog2Nlg2N)
这里的X表示每次爆枚出来的 1 0 d c + d b b ′ + 1 0 d c a ′ \frac {10^{dc+db}} {b'}+\frac {10^{dc}} {a'} b′10dc+db+a′10dc,官方题解说这和N一个级别。。我不太信。。。就稍微改了一下。。。
这种题感觉就像在猜一样。。。猜对了和出题人一样的算法就过。。。猜错了就过不去。。。(你tm就不能把N开成1e5???)
#include
#include
#include
#include
#define SF scanf
#define PF printf
#define MAXN 100010
#define INF 0x3FFFFFFF
using namespace std;
typedef long long ll;
ll pw2[20],pw5[20],pw10[20];
ll pr[20],maxv;
int tims[20],tot,n,cntt;
ll fsd(ll x,ll y,ll mod){
if(mod<INF)
return x*y%mod;
return (x*y-(ll)((long double)x/mod*y)*mod+mod)%mod;
// x%=mod;
// y%=mod;
// ll res=0;
// while(y){
// if(y&1ll)
// res=(res+x)%mod;
// x=(x+x)%mod;
// y>>=1ll;
// }
// return res;
}
ll fsp(ll x,ll y,ll mod){
ll res=1;
while(y){
if(y&1ll)
res=fsd(res,x,mod);
x=fsd(x,x,mod);
y>>=1ll;
}
return res;
}
ll gcd(ll x,ll y){
if(y==0)
return x;
return gcd(y,x%y);
}
ll prime[30]={2,3,5,7,11,13,17,19,23};
int cnt=9;
bool check(ll n){
if(n==1)
return 0;
if(n==2)
return 1;
if(n%2ll==0)
return 0;
for(int i=0;i<cnt;i++)
if(prime[i]==n)
return 1;
int k=0;
ll q=n-1;
while(q%2ll==0){
q>>=1ll;
k++;
}
for(int i=0;i<cnt;i++){
ll a=prime[i];
if(n<=a)
return 1;
ll y=fsp(a,q,n);
if(y==1)
continue;
bool flag=0;
for(int j=0;j<k;j++){
if(y==n-1){
flag=1;
break;
}
y=fsd(y,y,n);
}
if(flag)
continue;
return 0;
}
return 1;
}
ll po(ll n,ll c){
ll x=2,y=2,g=1;
while(g==1){
x=fsd(x,x,n)+c;
y=fsd(y,y,n)+c;
y=fsd(y,y,n)+c;
g=gcd(max(x-y,y-x),n);
}
if(g==n)
return po(n,c+1ll);
return g;
}
ll solve(ll x){
if(x%2==0)
return 2;
ll ans=x;
while(check(x)==0){
ll s=po(x,1);
ll res=solve(s);
ans=min(ans,res);
x/=s;
}
return min(x,ans);
}
int ans=0;
int cntc=0;
int dcx,dbx;
ll ax,bx;
void dfs(int x,ll d){
if(d>maxv||bx*d>=pw10[dbx]||ax*d*bx*d>=pw10[dcx])
return ;
if(x==tot+1){
ll a=ax*d,b=bx*d;
if(pw10[dbx-1]>b)
return ;
ll c=a*b;
if(pw10[dcx-1]>c)
return ;
ans++;
return ;
}
for(int i=0,p=1;i<=tims[x];i++,p=p*pr[x])
dfs(x+1,d*p);
}
vector<ll> prc;
void calc(int dc,int db,ll a,ll b){
ll val=pw10[dc+db]/b+pw10[dc]/a;
if(a>n||b>n)
return ;
tot=0;
maxv=min(n/a,n/b);
while(val!=1){
ll p=solve(val);
if(p>maxv)
break;
val/=p;
if(pr[tot]!=p){
pr[++tot]=p;
tims[tot]=0;
}
tims[tot]++;
}
// for(int i=1;i<=tot;i++)
// PF("<%lld %d>",pr[i],tims[i]);
// PF("\n");
dcx=dc,dbx=db,ax=a,bx=b;
dfs(1,1);
// PF("[%d]\n",ans);
}
int main(){
SF("%d",&n);
pw10[0]=pw5[0]=pw2[0]=1;
for(int i=1;i<=18;i++){
pw10[i]=pw10[i-1]*10;
pw5[i]=pw5[i-1]*5;
pw2[i]=pw2[i-1]*2;
}
for(int dc=1;dc<=12;dc++)
for(int db=1;pw10[db-1]<=n;db++)
for(int x1=0;x1<=dc&&pw2[x1]<=n;x1++)
for(int y1=0;y1<=dc&&pw2[x1]*pw5[y1]<=n;y1++)
for(int x2=0;x2<=(x1==0)*(db+dc);x2++)
for(int y2=0;y2<=(y1==0)*(db+dc);y2++)
calc(dc,db,pw2[x1]*pw5[y1],pw2[x2]*pw5[y2]);
PF("%d",ans);
}