C++复习(十五)——素数幻方

 

问题三十一:素数幻方 ,在一个4*4矩阵中,每一行,每一列,两条对角线上的四个数字组成的四位数均为可逆素数,求所有矩阵

/*
题目三十一:素数幻方 ,在一个4*4矩阵中,每一行,每一列,两条对角线上的四个数字组成的四位数均为可逆素数,求所有矩阵

分析:可逆素数可以判断,但是如果4*4方阵全部穷举,所需要的计算量极大
短时间内根本无法得出结果,需要化简问题 ,因为行数列数对角线均为可逆
素数,所以可以先求出所有的四位可逆素数进行穷举,计算量大大减少,因为是素数
所以每一行的末尾,每一列的末尾不可出现2的倍数和5倍数的数字,进一步缩减穷举
数据范围,在进行穷举则可得结果 
1、第一行,第一列不能有零
2、最后一行,最后一列不能有2,5的倍数
3、四位可逆素数
4、测试前两行 
5、测试前三行
6、输出结果 

*/
#include<iostream>
#include<cmath>
#define MAX 500
using namespace std;

int all_sum;
int last_all_sum;
int first_all_sum;

int ke_ni(int n){//返回逆数 
	int i,num = n,total = 0;
	int k,now = 1;
	for(i = 0;i<4;i++){
		for(k = 3;k>i;k--){
			now *= 10;
		}
		total += num%10*now;
		num /= 10;
		now = 1;
	}
	return total;
}

int su_shu(int n){//判断是否为素数 
	int i,now;
	if(n==1||n==0)return 0;
	if(n==2)return 1; 
	now = (int)sqrt((double)n) + 1;
	//now = n>>1;
	for(i = 2;i<=now;i++){
		if(n%i == 0)return 0;
	}
	return 1;
}

int get_n(int num,int i){//返回数n的第i位值 
	int last;
	for(;i > 1;i--){
		num /= 10;
	}
	last = num%10;
	return last;
}

int last_row_len(int n){
	int i;
	for(i=1;i<=4;i++){
		if(get_n(n,i)%2 == 0||get_n(n,i)%5 == 0){
			return 0;
		}
	}
	return 1;
}

int first_row_len(int n){
	int i;
	for(i=1;i<=4;i++){
		if(get_n(n,i) == 0){
			return 0;
		}
	}
	return 1;
}

int yes(int *all,int *first,int *last,int a,int b,int c,int d){
	int i;
	int flag = 0;
	for(i = 0;i<first_all_sum;i++){
		if(first[i] == get_n(a,4)*1000+get_n(b,4)*100+get_n(c,4)*10+get_n(d,4)){
			flag++;
			break;
		}
	}
	if(flag != 1)return 0;
	for(i = 0;i<all_sum;i++){
		if(all[i] == get_n(a,3)*1000+get_n(b,3)*100+get_n(c,3)*10+get_n(d,3)){
			flag++;
			break;
		}
	}
	if(flag != 2)return 0;
	for(i = 0;i<all_sum;i++){
		if(all[i] == get_n(a,2)*1000+get_n(b,2)*100+get_n(c,2)*10+get_n(d,2)){
			flag++;
			break;
		}
	}
	if(flag != 3)return 0;
	for(i = 0;i<last_all_sum;i++){
		if(last[i] == get_n(a,1)*1000+get_n(b,1)*100+get_n(c,1)*10+get_n(d,1)){
			flag++;
			break;
		}
	}
	if(flag != 4)return 0;
	for(i = 0;i<all_sum;i++){
		if(all[i] == get_n(a,4)*1000+get_n(b,3)*100+get_n(c,2)*10+get_n(d,1)){
			flag++;
			break;
		}
	}
	if(flag != 5)return 0;
	for(i = 0;i<all_sum;i++){
		if(all[i] == get_n(a,1)*1000+get_n(b,2)*100+get_n(c,3)*10+get_n(d,4)){
			flag++;
			break;
		}
	}
	if(flag != 6)return 0;
	return 1;
}

int yes_two(int *all,int *first,int *last,int a,int b){
	int i;
	int flag = 0;
	for(i = 0;i<first_all_sum;i++){
		if(get_n(first[i],4)*10+get_n(first[i],3) == get_n(a,4)*10+get_n(b,4)){
			flag++;
			break;
		}
	}
	if(flag != 1)return 0;
	for(i = 0;i<all_sum;i++){
		if(get_n(all[i],4)*10+get_n(all[i],3) == get_n(a,3)*10+get_n(b,3)){
			flag++;
			break;
		}
	}
	if(flag != 2)return 0;
	for(i = 0;i<all_sum;i++){
		if(get_n(all[i],4)*10+get_n(all[i],3) == get_n(a,2)*10+get_n(b,2)){
			flag++;
			break;
		}
	}
	if(flag != 3)return 0;
	for(i = 0;i<last_all_sum;i++){
		if(get_n(last[i],4)*10+get_n(last[i],3) == get_n(a,1)*10+get_n(b,1)){
			flag++;
			break;
		}
	}
	if(flag != 4)return 0;
	for(i = 0;i<all_sum;i++){
		if(get_n(all[i],4)*10+get_n(all[i],3) == get_n(a,4)*10+get_n(b,3)){
			flag++;
			break;
		}
	}
	if(flag != 5)return 0;
	for(i = 0;i<all_sum;i++){
		if(get_n(all[i],4)*10+get_n(all[i],3) == get_n(a,1)*10+get_n(b,2)){
			flag++;
			break;
		}
	}
	if(flag != 6)return 0;
	return 1;
} 

int yes_three(int *all,int *first,int *last,int a,int b,int c){
	int i;
	int flag = 0;
	for(i = 0;i<first_all_sum;i++){
		if(get_n(first[i],4)*100+get_n(first[i],3)*10+get_n(first[i],2) == get_n(a,4)*100+get_n(b,4)*10+get_n(c,4)){
			flag++;
			break;
		}
	}
	if(flag != 1)return 0;
	for(i = 0;i<all_sum;i++){
		if(get_n(all[i],4)*100+get_n(all[i],3)*10+get_n(all[i],2) == get_n(a,3)*100+get_n(b,3)*10+get_n(c,3)){
			flag++;
			break;
		}
	}
	if(flag != 2)return 0;
	for(i = 0;i<all_sum;i++){
		if(get_n(all[i],4)*100+get_n(all[i],3)*10+get_n(all[i],2) == get_n(a,2)*100+get_n(b,2)*10+get_n(c,2)){
			flag++;
			break;
		}
	}
	if(flag != 3)return 0;
	for(i = 0;i<last_all_sum;i++){
		if(get_n(last[i],4)*100+get_n(last[i],3)*10+get_n(last[i],2) == get_n(a,1)*100+get_n(b,1)*10+get_n(c,1)){
			flag++;
			break;
		}
	}
	if(flag != 4)return 0;
	for(i = 0;i<all_sum;i++){
		if(get_n(all[i],4)*100+get_n(all[i],3)*10+get_n(all[i],2) == get_n(a,4)*100+get_n(b,3)*10+get_n(c,2)){
			flag++;
			break;
		}
	}
	if(flag != 5)return 0;
	for(i = 0;i<all_sum;i++){
		if(get_n(all[i],4)*100+get_n(all[i],3)*10+get_n(all[i],2) == get_n(a,1)*100+get_n(b,2)*10+get_n(c,3)){
			flag++;
			break;
		}
	}
	if(flag != 6)return 0;
	return 1;
}

int main(){
	int i,count=0,j = 0;
	int all_su[MAX];
	for(i=1000;i<=9999;i++){
		if(su_shu(i)==1&&su_shu(ke_ni(i))==1){
			count++;
			all_su[j] = i;
			j++;
			//cout<<i<<" ";
		}
	}
	all_sum = j;
	int last[MAX],k=0;
	for(i=0;i<all_sum;i++){
		if(last_row_len(all_su[i]) == 1){
			last[k] = all_su[i];
			//cout<<last[k]<<" ";
			k++;
		}
	}
	last_all_sum = k;
	k = 0;
	int first[MAX];
	for(i=0;i<all_sum;i++){
		if(first_row_len(all_su[i]) == 1){
			first[k] = all_su[i];
			//cout<<first[k]<<" ";
			k++;
		}
	}
	first_all_sum = k;
	//方法一,速度有所提升,但仍然很慢 
	/*
	int all[MAX][MAX];
	int x;
	int a=0;
	for(i = 0;i<first_all_sum;i++){
		for(j = 0;j<all_sum;j++){
			for(k = 0;k<all_sum;k++){
				for(x = 0;x<last_all_sum;x++){
					if(yes(all_su,first,last,first[i],all_su[j],all_su[k],last[x])==1){
						cout<<first[i]<<'\n'<<all_su[j]<<'\n'<<all_su[k]<<'\n'<<last[x]<<'\n'<<endl;
						a++;
					}
				}
			}
		}
	}
	cout<<a<<endl;
	*/
	
	//方法二,速度极大提升 
	int x;
	int a=0;
	for(i = 0;i<first_all_sum;i++){
		for(j = 0;j<all_sum;j++){
			if(yes_two(all_su,first,last,first[i],all_su[j])==0)continue;
			for(k = 0;k<all_sum;k++){
				if(yes_three(all_su,first,last,first[i],all_su[j],all_su[k])==0)continue;
				for(x = 0;x<last_all_sum;x++){
					if(yes(all_su,first,last,first[i],all_su[j],all_su[k],last[x])==1){
						cout<<first[i]<<'\n'<<all_su[j]<<'\n'<<all_su[k]<<'\n'<<last[x]<<'\n'<<endl;
						a++;
					}
				}
			}
		}
	}
	cout<<a<<endl;
	return 0;
}

       这其中有不合适或者不正确的地方欢迎指正,我的QQ号码:2867221444(乔金明),谢谢,也可以相互交流下,备注信息随意,只要能看得出是开发者或者学习者即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值