1425:质数和
描述
有一个a+b位的正整数,前a位是质数,后b位也是质数,求所有符合条件的数字和。
注意:前a位的质数不可以0开头,否则拼出的数字不是a+b位。后b位的质数可以是0开头。例如当a=1,b=2时,207是一个符合条件的数字。
输入
多组案例。一个正整数n,表示案例的数量。(n<=40)
每组案例由两个正整数a和b组成(1<=a<=7,1<=b<=7,且保证a+b<=10)
输出
针对每组案例,输出一个长整数,表示所有符合条件的数字和。
每组案例输出完都要换行。
样例输入
2
1 2
5 5
样例输出
46740
430358607365438931
#include<iostream>
#include<cmath>
#include<memory>
using namespace std;
typedef unsigned char BYTE;//无符号单字节的东西
bool getValue(BYTE* s, int number)
{
return s[number / 8] & (1 << (number % 8));
//当number=2时,return s[0]&(1<<2)
//11111100 & 00000100 = 00000100 -> true
//11111000 & 00000100 = 00000000 -> false
//true->number 是质数 false->number 不是质数
}
void setValue(BYTE* s, int number)
{
BYTE t = ~(1 << (number % 8));
s[number / 8] &= t;
//当number=4时,s[0]=11111100,1 << 4 = 00010000
//t = 11101111
//s[0] = s[0]&t
//11111100&11101111=11101100
}
int power(int a, int b)
{
int mul = 1;
for (int i = 0; i < b; i++)
{
mul *= a;
}
return mul;
}
int main()
{
//用埃拉托斯特尼筛法检测质数。用一个位记录某个数字是不是质数,数字x在s[x/8]的第x%8个位上(最低位为第0位)
const int MAX = 10000000;
BYTE* s = new BYTE[MAX / 8];
for (int i = 0; i < MAX / 8; i++)//假设都是质数
{
s[i] = 255;//二进制11111111
}
s[0] = s[0] ^ 3;
//0和1不是质数(00000000~11111111=11111100)
for (int i = 2; i <= sqrt(MAX); i++)
{
if (getValue(s, i))
{
for (int j = i * i; j < MAX; j += i)
{
setValue(s, j);
}
}
}
unsigned long long int t[8] = { 0 };
//t[i]表示i位数中质数的和
unsigned long long int t2[8] = { 0 };
//t的累加,t2[3]表示3位数+2位数+1位数的和
unsigned int u[8] = { 0 };
//u[i]表示i位数中质数的个数
unsigned int u2[8] = { 0 };
//u的累加
int v = 1;
for (int i = 1; i <= 7; i++)
{
for (int j = v; j < v * 10; j++)
{
if (getValue(s, j))
{
t[i] += j;
u[i]++;
}
}
v *= 10;
}
for (int i =1;i<=7;i++)
{
t2[i] = t2[i - 1] + t[i];
//t2[2]=t2[1]+t[2]=t[1]+t[2]
u2[i] = u2[i - 1] + u[i];
}
delete[]s;
int n;
cin >> n;
while (n--)
{
int a, b;
cin >> a >> b;
unsigned int c = power(10, b);
unsigned long long int result = t[a] * u2[b] * c + t2[b] * u[a];
cout << result << endl;
}
return 0;
}