【复杂度玄学】【数学】省选模拟51nod 乘法表

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/88940490

分析:

搞不懂为什么理论复杂度那么大。。但是的确跑不满。。。

根据题意,得到
g 1 0 d c + d b b + 1 0 d c a g|\frac {10^{dc+db}} {b'}+\frac {10^{dc}} {a'}
其中 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 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)

这里的X表示每次爆枚出来的 1 0 d c + d b b + 1 0 d c a \frac {10^{dc+db}} {b'}+\frac {10^{dc}} {a'} ,官方题解说这和N一个级别。。我不太信。。。就稍微改了一下。。。

这种题感觉就像在猜一样。。。猜对了和出题人一样的算法就过。。。猜错了就过不去。。。(你tm就不能把N开成1e5???)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstring>
#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);
}

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/88940490