小明的密码
描述
小明的密码由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 ",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 ",ans); } else { Mplus(M); } } return 0; }