GCJ 2016 资格赛 C题

很有意思的题啊~~


核心问题,如何快速判断合数~~


然后你想啊,那么多数字满足条件的一定非常多,那么只要这个数字有因子,就一定是合数。  


而且题目并没有需要你输出前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;
}



你可能感兴趣的:(GCJ 2016 资格赛 C题)