Description
如果一个数任意相邻两位均是质数,我们称之为 大蒜数。最小的大蒜数是两位数 11。蒜头君想知道 K 位数的大蒜数有多少个。
Input
输入为 1 个整数 K,(2≤K≤1000)。
测试点编号 | K |
---|---|
1 | K=2 |
2-3 | 3≤K≤8 |
4-6 | 9≤K≤11 |
7-10 | 12<K≤1000 |
Output
输出为 1 个整数,为 K 位数的大蒜数的个数,结果对 10007 取模。
Sample Input
5
Sample Output
372
由于只需要每个相邻两位为质数,故我们只需要用到两位的质数,预处理出这些质数,并将其作为一个坐标保存在prime数组里面。采取dp的思想,从前往后推,其中i表示位数,j表示前一个数,k表示后一个数,由于k只可能是奇数所以在遍历的时候直接k+=2。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int prime[100][100];
int vis[100];
int dp[1001][10];
const int mod=10007;
void sieve()
{
vis[0]=1;vis[1]=1;
vis[2]=0;
for(int i=2;i<=100;i+=2)
vis[i]=1;
for(int i=3;i*i<=100;i+=2)
{
if(!vis[i])
{
for(int j=i;j*i<=100;j++)
{
vis[i*j]=1;
}
}
}
for(int i=11;i<99;i++)
{
if(!vis[i])
{
prime[i/10][i%10]=1;
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
sieve();
int n;
cin>>n;
for(int i=1;i<=9;i++)
dp[1][i]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=9;j++)
{
for(int k=1;k<=9;k+=2)
{
if(prime[j][k])
{
dp[i][k]+=dp[i-1][j];
dp[i][k]%=mod;
}
}
}
}
ll res=0;
for(int i=1;i<=9;i+=2)
{
res+=dp[n][i];
res%=mod;
}
cout<<res<<endl;
return 0;
}