链接:https://nanti.jisuanke.com/t/35618
题意:
如果一个数大于等于 1010 且任意连续两位都是质数,那么就称之为 Wish 数。当然,第一个 Wish 数是 1111。
比如 9797,111111,131131,119119 都是 Wish 数,而 1212,136136 则不是。问第 NN 个 Wish 数是多少。
思路:预处理一下 1 - 9 每个数后面可以跟的能够与它组成两位数字并且为素数的数字。
dp[ i ] [ j ] i 的含义是 i 长度为i 的数字,开头为 j 的 wish 数,那么他就可以由 dp [ i - 1] [ 预处理的 g[ j ] ]转移而来
需要cnt [ i ]存储的是 长度为 i 的总数 ,最后根据n 去具体定位那个数,可以先确定是个几位数 。然后从 高位开始确定每一位数字是什么。
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxn 123 vector<int>g[123],ans; ll n,cnt[maxn+1],sum,x; ll dp[maxn+10][13]; bool isprime[maxn+10]; void getprim() { isprime[0]=isprime[1]=1; for(int i=2; i<=sqrt(maxn); i++) for(int j=i*i; j<maxn; j+=i) isprime[j]=1; } int main() { getprim(); scanf("%lld",&n); for(int i=1; i<10; i++) for(int j=1; j<10; j++) if(isprime[i*10+j]==0)g[i].push_back(j); for(int i=1; i<10; i++)g[10].push_back(i); for(int i=2; i<50; i++) for(int j=1; j<10; j++) { for(int k=0; k<g[j].size(); k++) dp[i][j]+=(i==2?1:dp[i-1][g[j][k]]); cnt[i]+=dp[i][j]; } for(int i=2; i<50; i++) { if(sum+cnt[i]<n) sum+=cnt[i]; else { n-=sum; x=10; for(int k=i; k>=2; k--) for(int u=0; u<g[x].size(); u++) { int v=g[x][u]; if(n-dp[k][v]<=0) { ans.push_back(v); x=v; break; } else n-=dp[k][v]; } ans.push_back(g[x][n-1]); break; } } for(int i=0; i<ans.size(); i++) printf("%d",ans[i]); printf("\n"); return 0; }