小明的密码(代码精简版)

小明的密码

描述

小明的密码由N(1<=N<=12)个数字构成,每个数字都可以是0至9中任意一个数字,但小明的密码还有
一个特点就是密码中连续的M(1<=M<=4)个数字的和是质数,现给定M和N,求满足条件的密码共有多少
个?

 

 

输入格式

第1行是T,case数量,此后T行,每行两个数,N和M

 

输出格式

每个case输出一个满足条件的密码总数

#include <cstdlib>
#include <cstdio>
#include  <cstring>
using namespace std;
int visited[5][20][9009];// 访问情况
int dp[5][20][9009];  // M N num num即M-1位的数字
int num_2[7]= {2,3,5,7,11,13,17};
int num_3[9]= {2,3,5,7,11,13,17,19,23};
int num_4[11]= {2,3,5,7,11,13,17,19,23,29,31};  //存储素数
int N,M,T;
int delete_head(int num,int m)  //去掉当前数字的首个数字
{
    int ans;
    if (m==2) return 0;
    if (m==3) ans=num-num/10*10;
    if (m==4) ans=num-num/100*100;
    return ans;
}
int divide_num(int num)
{
    int ans=0;
    while (num>0)
    {
        ans+=num;
        num=num/10;
    }
    return ans;
}
int select_num(int k,int sum,int m)
{
    if (m==2)
    {
        for (int i=0; i<7; i++) if (k+divide_num(sum)==num_2[i]) return 1;
        return 0;
    }
    if (m==3)
    {
        for (int i=0; i<9; i++) if (k+divide_num(sum)==num_3[i])  return 1;
        return 0;
    }
    if (m==4)
    {
        for (int i=0; i<11; i++) if (k+divide_num(sum)==num_4[i]) return 1;
        return 0;
    }
}
void work(int m,int n,int num)
{
    if (n==0)  // n=0直接处理
    {
        visited[m][n][num]=1;
        dp[m][n][num]=1;
    }
    else
    {
        if (!visited[m][n][num])
        {
            visited[m][n][num]=1;
            for (int k=0; k<=9; k++)
            {
                if (select_num(k,num,m))
                {
                    int next=delete_head(num,m)*10+k; //next是num的下个状态(去头加尾)
                    if (!visited[m][n-1][next])
                    {
                        work(m,n-1,next);
                    }
                    dp[m][n][num]+=dp[m][n-1][next];
                }
            }
        }
    }
}

int Mp(int T){
    int returnNum=1;
    T--;
    while (T--){
        returnNum=returnNum*10;
    }
    return returnNum-1;
}
int Mplus(int M){
int num=1,ans=0,cont=Mp(M);
    for (int i=0;i<=cont;i++){
        work(M,N-M+1,i);
        ans+=dp[M][N-M+1][i];
    }
    printf("%d\n",ans);
}

int main()
{
    memset(visited,0,sizeof(visited));
    memset(dp,0,sizeof(dp));
    scanf("%d",&T);
    while (T--){
        scanf("%d %d",&N,&M);
    if (M==1)
    {
        int ans=1;
        while (N>0)
        {
            ans*=4;
            N--;
        }
        printf("%d\n",ans);
    }
    else {
        Mplus(M);
    }
    }

    return 0;
}
View Code

 

posted @ 2020-07-19 15:15  LionelTens  阅读(390)  评论(0编辑  收藏  举报