Infiniti

   :: 首页  :: 新随笔  ::  ::  :: 管理

链接: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;
}

  

posted on 2019-01-20 14:26  自由缚  阅读(325)  评论(0编辑  收藏  举报