USACO4.3.2——质数方阵暴力解法

题面链接:这里;

读过题后,就不难发现这是一道填数题,先说填法,大多数人一开始肯定想到一行行填,一列列填,填完后整体判断——大数据直接把你T废:

于是我们就开始关注一些已经确定的点,确定的点越多,可供选择的素数就越少,运行速度就越快,请看下图:

图中的深红色(最左上角)表示题目中确定的点,我们先填第一行第一列(红色),这样有一个约束条件(一头确定),再填右上-左下的那条斜边(紫色),这样有两个约束条件(一头一尾已经确定),再填左上-右下的那条斜边(深蓝),再填浅蓝和绿色,它们都有两个约束条件。最后算出橙色的值,用总值减去其他四个数的值,如果是负数或大于10,就退回来重新做。

整体做完后,按照题目所给的条件进行判断,不符合就退回来重新做。

输出答案前需要先排序,将答案二维数组存到一个字符串中,这样就可以方便比较。

这里需要重点提的一点便是判质,下面是我刚开始写的一段代码:

bool Judge_Num(int Num) {for (register int i = 2; i <= sqrt(Num); i++)if (Num % i == 0)return false;// cout<<Num<<endl;return true;
}

注意,它会爆——每次循环计算一次sqrt是很耗时间的,所以,我做了以下改进:

bool Judge_Num(int Num) {int T=sqrt(Num);//这样只要计算一次sqrtfor (register int i = 2; i <= T; i++)if (Num % i == 0)return false;// cout<<Num<<endl;return true;
}

可是还是会超时(Num是一个五位数,每次循环少说也要100次),能不能将判质时间缩到O(1)呢?
可以的:
我们在填数之前先用欧拉筛将10000到99999中的素数筛出来,用bool数组Visited储存,Visited[N]=1表示N是质数,Visited[N]=0表示N是不是质数,这样,每次判质时,我们只需要:

bool Judge_Num(int Num){return true-Visited[Num];
}

万事大吉

代码(号称USACO史上最长):

#include "bits/stdc++.h"
using namespace std;struct Unsigned {int Size, Num[1001];int E[1001][11];
} Prime[11];//储存每一个素数
int Sum, Start, Used[9], Result[9][9], Size, prime[100100];
bool Can, Visited[100101];
const int N = 5, M = 9;struct Out {string Name;int Num_Result[9][9];friend bool operator<(Out Num1, Out Num2) { return Num1.Name < Num2.Name; }
} HaHaHa[999];
//答案的排序void Made_Prime(void) {for (int i = 2; i <= 100100; i++) {if (!Visited[i])prime[++prime[0]] = i;for (int j = 1; j <= prime[0] && i * prime[j] <= 100100; j++) {Visited[i * prime[j]] = 1;if (i % prime[j] == 0)break;}}return;
}//欧拉筛bool Judge_Num(int Num) { return true - Visited[Num];
}//判质void DFS_Made(int K, int Last, int Already) {if (Last > 9 * (N - K))return;if (K == N) {if (Last == 0 && Judge_Num(Already) == true) {int JJ = Already, KK = N;++Prime[Already / 10000].Size;int UU = Prime[Already / 10000].Size;Prime[Already / 10000].Num[UU] = Already;while (JJ != 0) {Prime[Already / 10000].E[UU][KK] = JJ % 10;KK--, JJ = JJ / 10;}}return;}for (register int i = 0; i <= 9; i++) DFS_Made(K + 1, Last - i, Already * 10 + i);return;
}//将合法五位素数整出来bool Judge(void) {int Sum_Judge = 0, Mul_Judge = 0;for (register int i = 1; i <= N; i++) {Sum_Judge = 0;for (register int j = 1; j <= N; j++) Sum_Judge = Sum_Judge + Result[j][i];if (Sum_Judge != Sum)return false;}for (register int i = 1; i <= N; i++) {Mul_Judge = 0;for (register int j = 1; j <= N; j++) Mul_Judge = Mul_Judge * 10 + Result[j][i];if (Judge_Num(Mul_Judge) == false)return false;}for (register int i = 1; i <= N; i++) {Sum_Judge = 0;for (register int j = 1; j <= N; j++) Sum_Judge = Sum_Judge + Result[i][j];if (Sum_Judge != Sum)return false;}for (register int i = 1; i <= N; i++) {Mul_Judge = 0;for (register int j = 1; j <= N; j++) Mul_Judge = Mul_Judge * 10 + Result[i][j];if (Judge_Num(Mul_Judge) == false)return false;}Sum_Judge = 0, Mul_Judge = 0;for (register int i = 1; i <= N; i++) {Mul_Judge = Mul_Judge * 10 + Result[i][i];Sum_Judge = Sum_Judge + Result[i][i];}if (Sum_Judge != Sum || Judge_Num(Mul_Judge) == false)return false;Sum_Judge = 0, Mul_Judge = 0;for (register int i = 1; i <= N; i++) {Mul_Judge = Mul_Judge * 10 + Result[N - i + 1][i];Sum_Judge = Sum_Judge + Result[N - i + 1][i];}if (Sum_Judge != Sum || Judge_Num(Mul_Judge) == false)return false;return true;
}bool Judge_Zero(int *QQ) {for (register int i = 1; i <= N; i++)if (QQ[i] == 0)return false;return true;
}//对矩阵的合法性进行判断int main(void) {cin >> Sum >> Start;if (Sum < Start + 4 || Sum % 3 == 0) {cout << "NONE" << endl;return 0;}//如果总和太小或每个五位数是三的倍数,直接无解Made_Prime();for (register int i = 1; i <= 9; i++) DFS_Made(1, Sum - i, i);
//将素数整出来
//以下代码比较长,其实就是将数填进格子中for (register int ii = 1; ii <= Prime[Start].Size; ii++) {if (Judge_Zero(Prime[Start].E[ii]) == true) {for (register int i = 1; i <= N; i++) Result[1][i] = Prime[Start].E[ii][i];for (register int iii = 1; iii <= Prime[Start].Size; iii++) {if (Judge_Zero(Prime[Start].E[iii]) == true) {for (register int i = 1; i <= N; i++) Result[i][1] = Prime[Start].E[iii][i];int T = Result[N][1];for (register int i = 1; i <= Prime[T].Size; i++) {if (Prime[T].E[i][N] == Result[1][N]) {for (register int j = 1; j <= N; j++) Result[N - j + 1][j] = Prime[T].E[i][j];int Y = Result[3][1];for (register int j = 1; j <= Prime[Y].Size; j++) {if (Prime[Y].E[j][3] == Result[3][3]) {for (register int k = 1; k <= N; k++) Result[3][k] = Prime[Y].E[j][k];int D = Result[1][1];for (register int k = 1; k <= Prime[D].Size; k++) {if (Prime[D].E[k][3] == Result[3][3]) {for (register int l = 1; l <= N; l++)Result[l][l] = Prime[D].E[k][l];Result[N][2] = Sum - Result[1][2] - Result[2][2] - Result[3][2] -Result[4][2];if (Result[N][2] < 0 || Result[N][2] > 9)continue;int JJJJJJJ = 0, KKKKKKK = 1;while (KKKKKKK <= N) {JJJJJJJ = JJJJJJJ * 10 + Result[KKKKKKK][2];KKKKKKK++;}if (Judge_Num(JJJJJJJ) == false)continue;//填到一半的一个小剪枝int G = Result[1][3];for (register int l = 1; l <= Prime[G].Size; l++) {if (Prime[G].E[l][3] == Result[3][3]) {for (register int h = 1; h <= N; h++)Result[h][3] = Prime[G].E[l][h];Result[2][N] = Sum - Result[2][1] - Result[2][2] -Result[2][3] - Result[2][4];Result[4][N] = Sum - Result[4][1] - Result[4][2] -Result[4][3] - Result[4][4];Result[N][2] = Sum - Result[1][2] - Result[2][2] -Result[3][2] - Result[4][2];Result[N][4] = Sum - Result[1][4] - Result[2][4] -Result[3][4] - Result[4][4];if (Result[2][N] < 0 || Result[4][N] < 0 ||Result[N][2] < 0 || Result[N][4] < 0)continue;if (Result[2][N] > 9 || Result[4][N] > 9 ||Result[N][2] > 9 || Result[N][4] > 9)continue;
//合法性判断if (Judge() == true) {Can = true;Size++;for (register int iiii = 1; iiii <= N; iiii++) {for (register int jj = 1; jj <= N; jj++) {HaHaHa[Size].Num_Result[iiii][jj] =Result[iiii][jj];HaHaHa[Size].Name += ('0' + Result[iiii][jj]);}  // cout<<endl;}      // cout<<endl;}}}}}}}}}}}}}if (Can == false) {cout << "NONE" << endl;} else {sort(HaHaHa + 1, HaHaHa + 1 + Size);for (register int k = 1; k <= Size; k++) {for (register int i = 1; i <= N; i++) {for (register int j = 1; j <= N; j++) {cout << HaHaHa[k].Num_Result[i][j];}//排序并输出cout << endl;}cout << endl;}}return 0;
}

The End

USACO4.3.2——质数方阵暴力解法相关推荐

  1. loj.ac:#10024. 「一本通 1.3 练习 3」质数方阵

    CSDN的博客 友键 题目描述 质数方阵是一个\(5×5\)的方阵,每行.每列.两条对角线上的数字可以看作是五位的素数.方格中的行按照从左到右的顺序组成一个素数,而列按照从上到下的顺序.两条对角线也是 ...

  2. c语言暴力求解法二维数组比较,【算法】搜索二维矩阵 暴力解法二分法 4种语言...

    编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值.该矩阵具有如下特性: 每行中的整数从左到右按升序排列. 每行的第一个整数大于前一行的最后一个整数. 示例 1:输入:matrix = ...

  3. leetcode 221. Maximal Square | 221. 最大正方形(优化的暴力解法+动态规划解法)

    题目 https://leetcode.com/problems/maximal-square/ 题解 方法1:最暴力解 O((m*n)^2) public class Solution {publi ...

  4. 2013蓝桥杯C++A:排它平方数(递归,枚举,暴力解法)

    二.题目: 排它平方数 小明正看着 203879 这个数字发呆. 原来,203879 * 203879 = 41566646641 这有什么神奇呢?仔细观察,203879 是个6位数,并且它的每个数位 ...

  5. 算法实验 01背包 暴力解法 java实现

    01背包 暴力解法 01背包问题正如其名,其本质就是真和假,0和1.每个物品只有要么被装进背包,要么没有装进背包这两种状态.其暴力解法也算是一种全排列问题. 如上图所示,我们可以用一个数组used来表 ...

  6. Python如何实现将四位数字组合成一个不重复的三位数,for循环暴力解法

    Python如何实现将四位数字组合成一个不重复的三位数,for循环暴力解法 周末的时候遇到一个题目,看似很简单,但是在当时考试的情况下来说,我误判了,我没有把握好时间,导致我后面时间很紧,没有时间去思 ...

  7. 洛谷P2141珠心算测验 (枚举暴力解法)

    题目描述 珠心算是一种通过在脑中模拟算盘变化来完成快速运算的一种计算技术.珠心斜体样式算训练,既能够开发智力,又能够为日常生活带来很多便利,因而在很多学校得到普及. 某学校的珠心算老师采用一种快速考察 ...

  8. 求最长回文子串——C++ (动态规划+暴力解法)

    声明:本文原题主要来自力扣,记录此博客主要是为自己学习总结,不做任何商业等活动! 一.题目描述 给你一个字符串 s,找到 s 中最长的回文子串. 示例 1: 输入:s = "babad&qu ...

  9. 一道初等平面几何竞赛题的暴力解法

    问题 一道初中数学竞赛,平面几何题计算: 这里改成了证明题,反正思路是一样的. 暴力解法 中学的题就应该有中学的解法.但是,看习惯了高等数学的内容之后,更习惯暴力解法.暴力破解的方法是怎样的? 首先, ...

  10. KY16 求root(N, k)|模拟暴力解法

    模拟暴力解法失败,这个方法正确是正确的,但是提交的时候会运行超时 #include <stdio.h> #include <iostream> #pragma warning( ...

最新文章

  1. html标签一对一绑定的组件,一种原生组件替换HTML标签的轻量级方法尝试
  2. python opencv模板匹配多目标_基于opencv的多目标模板匹配
  3. C#在异常中获取HttpStatusCode用法
  4. Android 源码解析之AsyncTask
  5. pcb地线应该不应该做成环路_PCB制板的基础知识,你都学会了吗?(中)
  6. 数据结构与算法17-表插入排序
  7. 状态压缩 DP AHU420
  8. 就业寒冬,从拉勾招聘看Python就业前景
  9. ASP.Net学习笔记003--网站和WebApplication的区别
  10. 目标检测(六)--SPPNet
  11. 非线性最小二乘问题的分析与理解(附高斯牛顿法matlab代码)
  12. 软件工程毕业设计课题(1)基于python的毕业设计python疫苗预约系统毕设作品
  13. 泰克TDS3054B示波器技术指标
  14. 马斯克的新歌再次证明:不爱音乐的大老板不是一个好网红
  15. 名帖318 沈尹默 行书《行书帖选》
  16. 我的世界服务器如何修改天气,我的世界天气修改设置、天气关闭锁定、天气指令代码作弊码大全-66街机网...
  17. 使用md5进行加密解密
  18. 使用ICSharpZipLib进行压缩和解压(整理)
  19. JAVA----数字金额大写转换
  20. 《Kotlin 极简教程 》第6章 泛型

热门文章

  1. linux sfc模拟器,PSP适用SFC模拟器Snes9x完全使用教程
  2. 华为手机长按图片无法下载
  3. Vitalik:ETH2.0 之后,协议层会稳定下来
  4. android如何区分模拟器和真机
  5. d3d透视逆向篇:第5课:D3D9游戏黑屏优化2 DrawIndexedPrimitive
  6. Cisco交换机产品线和主要产品--- 型号说明
  7. java实现树形菜单_Java构建树形菜单的实例代码(支持多级菜单)
  8. 单独使用bable插件
  9. c# 通过读取Json文件生成HTML页并在浏览器显示
  10. linux 清空stdin缓冲,清除stdin缓存中的数据