很有意思的题啊~~
核心问题,如何快速判断合数~~
然后你想啊,那么多数字满足条件的一定非常多,那么只要这个数字有因子,就一定是合数。
而且题目并没有需要你输出前k个数字,所以可以这样……
定义一个数字叫:新合数,新合数是,这个数字有一个因子在2~1000之间。
显然,新合数一定是合数~ 那么我就不判断是否是非素数了,只要是新合数就可以啦~~~~ 这样程序巨快,飞速解决small的数据
那么large呢? 1e32…… 理论上也是可以这样做的,只不过套一个bigint的模板,或者用py或者java
当然还有更简单的方法~
一个数字100010100????01010011这样的数字转化为k进制的时候,进行一系列的乘,加运算…… 我们需要知道这个在彻底转化完成后,是否可以被p整除, 那么在转化的过程中就可以进行计算了……简单吧!
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <cmath>
#include <vector>
#include <bitset>
using namespace std;
#define LL long long
void nextInt(int &x)
{
scanf("%d", &x);
}
void nextInt(int &x, int &y)
{
scanf("%d%d", &x, &y);
}
int n, j;
LL qz;
void init()
{
nextInt(n, j);
qz = 1;
qz |= (1 << (n - 1));
}
int f[2000];
int output[1000];
bool check(long long arg)
{
bitset<60> a = arg;
for (int jinzhi = 2; jinzhi <= 10; ++ jinzhi)
{
memset(f, 0, sizeof(f));
for (int i = n - 1; i >= 0; -- i)
{
for (int j = 2; j <= 1000; ++ j)
{
if (a[i] == 0)
{
f[j] = (f[j] * jinzhi) % j;
}
else
{
f[j] = (f[j] * jinzhi + 1) % j;
}
}
}
for (int i = 2; i <= 1000; ++ i)
if (f[i] == 0)
{
output[jinzhi] = i;
goto here;
}
//没有执行到break?
return false;//arg在jinzhi的进制下,是素数
here:;
}
for (int i = n - 1; i >= 0; -- i) printf("%d", a[i] == 1);
printf(" ");
for (int i = 2; i <= 9; ++ i) printf("%d ", output[i]);
printf("%d\n", output[10]);
return true;
}
void doit()
{
int ans = 0;
for (LL i = 0; i < (1 << (n - 2)); ++ i)
{
if (check((i << 1LL) | qz)) ++ ans;
if (ans == j) break;
}
}
int main()
{
freopen("C-large.in","r",stdin);
freopen("C-large.out","w",stdout);
LL sb;
scanf("%lld", &sb);
for (int i = 1; i <= sb; ++ i)
{
printf("Case #%d:\n", i);
init();
doit();
}
return 0;
}