题目链接:http://codeforces.com/contest/568/problem/A
题目大意:定义 π ( n ) π(n) π(n)为不大于 n n n的素数个数, r u b ( n ) rub(n) rub(n)为不大于 n n n的回文数个数,给定两个数 p , q p,q p,q, A = p q A=\frac{p}{q} A=qp,找到最大的 n n n满足 π ( n ) ≤ A ⋅ r u b ( n ) π(n) ≤ A·rub(n) π(n) ≤ A⋅rub(n)。
题解:我们都知道不大于 n n n的素数个数大约为 n l o g ( n ) \frac{n}{log(n)} log(n)n,且可以发现长度为 k k k的回文数的个数大约为 1 0 ⌊ k + 1 2 ⌋ 10^{\lfloor \frac{k+1}{2} \rfloor} 10⌊2k+1⌋。随着 n n n的增大,素数的数量渐近地大于回文数的数量,且对于任意 A A A都有解,对于答案 n n n的下一个解满足 A ∼ n l o g ( n ) A\sim\frac{\sqrt {n}}{log(n)} A∼log(n)n。
那么我们可以线性预处理一下 n < 1 0 7 n<10^7 n<107以内的素数和回文数,然后就可以得到答案。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e7+10;
int a[maxn],prime[maxn],vis[maxn];
int pi[maxn],rub[maxn];
int is_palindrome(int n)
{
int tmp=n;
int sum=0;
while(tmp){
sum=sum*10+tmp%10;
tmp/=10;
}
if(sum==n){
return 1;
}
else{
return 0;
}
}
void solve()
{
for(int i=2;i<maxn;i++){
if(vis[i]==0){
prime[i]=1;
for(int j=2*i;j<maxn;j+=i){
vis[j]=1;
}
}
}
pi[1]=0;
rub[1]=1;
for(int i=2;i<maxn;i++){
pi[i]=pi[i-1]+prime[i];
rub[i]=rub[i-1]+is_palindrome(i);
}
}
double p,q;
int main()
{
cin>>p>>q;
solve();
int ans=maxn-1;
while(ans){
if(1.0*pi[ans]/(1.0*rub[ans])<=p/q){
break;
}
ans--;
}
cout<<ans<<endl;
return 0;
}