[USACO 6.4.1] The Primes

题目大意

  给一个5*5的矩阵,在每个格子里面填入0~9这10个数字.要求行从左往右读,列从上往下读,两条对角线从上往下读是一个5位素数且不含前导0.

  现在给出了开头的数字和行,列,对角线之和,求符合规定的所有数字矩阵.

题解

  这是一道搜索题.

  但盲目的搜索是会TLE的.因此,我们应当采用合理的剪枝.

  由题目可知,加入行列对角线我们知道了任意4位数,我们可以推出第5位数是什么.

  因此,我们可以采用传说中的手动指定搜索顺序的方法来搜索和回溯.

  具体搜索顺序如下图.

  大概就是这样的感觉.

  里面的C是可以直接算出来的.所以我们只需要搜索只有数字那些就行了.

  还有我一开始是枚举对角线素数.

  注意: 先枚举每个数的最后一位会让你减少至少一半的搜索量.因为5位素数的最后一位数肯定不是偶数.

  详情请看代码.代码有点恶心.我用了宏定义,因为这样看起来会更加恶心.

代码

/*
TASK:prime3
LANG:C++
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#define REP(i,st,ed) for ((i) = (st); (i) < (ed); ++(i))

using namespace std;

struct Ans
{
    int matrix[5][5];

    Ans operator = (Ans &rhs)
    {
        memcpy(matrix, rhs.matrix, sizeof(rhs.matrix));
        return *this;
    }

    bool operator < (const Ans &rhs) const
    {
        for (int i = 0; i < 5; ++i)
            for (int j = 0; j < 5; ++j)
                if (matrix[i][j] < rhs.matrix[i][j]) return true;
                else if (matrix[i][j] > rhs.matrix[i][j]) return false;
        return false;
    }

}ans[1000], tmp;
int anslen;

const int MAXP = 100000;
int p[10000], np, sumallr[5], sumallc[5], sumalld, sum;
bool v[MAXP * 10];

bool check(int x)
{
    int s = 0;
    while (x) s += x % 10, x /= 10;
    return s == sum;
}

void filtrate()
{
    memset(v, true, sizeof(v));
    for (int i = 2; i < MAXP; ++i)
        for (int j = 2; i * j < MAXP; ++j)
            v[i * j] = false;
    np = 0;
    for (int i = 10000; i < MAXP; ++i)
        if (v[i] && check(i)) p[np++] = i;
}

bool judge(int x, int y)
{
    if (sumallr[x] + tmp.matrix[x][y] > sum) return false;
    if (sumallc[y] + tmp.matrix[x][y] > sum) return false;
    if (4 - x == y && sumalld + tmp.matrix[x][y] > sum) return false;
    return true;
}

void adds(int x, int y, int d)
{
    sumallr[x] += tmp.matrix[x][y] * d;
    sumallc[y] += tmp.matrix[x][y] * d;
    if (4 - x == y) sumalld += tmp.matrix[x][y] * d;
}

int trans(int d, int m)
{
    if (m == 1) return tmp.matrix[d][0] * 10000
                        + tmp.matrix[d][1] * 1000
                        + tmp.matrix[d][2] * 100
                        + tmp.matrix[d][3] * 10
                        + tmp.matrix[d][4];
    else if (m == 2) return tmp.matrix[0][d] * 10000
                            + tmp.matrix[1][d] * 1000
                            + tmp.matrix[2][d] * 100
                            + tmp.matrix[3][d] * 10
                            + tmp.matrix[4][d];
    else if (m == 3) return tmp.matrix[4][0] * 10000
                            + tmp.matrix[3][1] * 1000
                            + tmp.matrix[2][2] * 100
                            + tmp.matrix[1][3] * 10
                            + tmp.matrix[0][4];
}

bool condit(int x)
{
    return x >= 0 && x <= 9;
}

int main()
{
    freopen("prime3.in", "r", stdin);
    freopen("prime3.out", "w", stdout);
    scanf("%d%d", &sum, &tmp.matrix[0][0]);
    filtrate();
    memset(sumallr, 0, sizeof(sumallr));
    memset(sumallc, 0, sizeof(sumallc));
    sumalld = 0;
    anslen = 0;
    for (int i = 0; i < np; ++i)
    {
        if (p[i] * 10 / MAXP != tmp.matrix[0][0]) continue;
        int k = p[i];
        for (int j = 4; j >= 0; --j)
        {
            tmp.matrix[j][j] = k % 10;
            sumallr[j] = sumallc[j] = k % 10;
            k /= 10;
        }
        sumalld = p[i] % 1000 / 100;
        REP(tmp.matrix[0][4], 1, 10)
        {
            if (tmp.matrix[0][4] % 2 == 0 || tmp.matrix[0][4] == 5) continue;
            if (!judge(0, 4)) break;
            adds(0, 4, 1);
            REP(tmp.matrix[1][3], 0, 10)
            {
                if (!judge(1, 3)) break;
                adds(1, 3, 1);
                REP(tmp.matrix[4][0], 1, 10)
                {
                    if (tmp.matrix[4][0] % 2 == 0 || tmp.matrix[4][0] == 5) continue;
                    if (!judge(4, 0)) break;
                    tmp.matrix[3][1] = sum - sumalld - tmp.matrix[4][0];
                    if (!condit(tmp.matrix[3][1]) || !judge(3, 1)) continue;
                    if (!v[trans(0, 3)]) continue;
                    adds(3, 1, 1);
                    adds(4, 0, 1);
                    REP(tmp.matrix[1][4], 1, 10)
                    {
                        if (tmp.matrix[1][4] % 2 == 0 || tmp.matrix[1][4] == 5) continue;
                        if (!judge(1, 4)) break;
                        adds(1, 4, 1);
                        REP(tmp.matrix[2][4], 1, 10)
                        {
                            if (tmp.matrix[2][4] % 2 == 0 || tmp.matrix[2][4] == 5) continue;
                            if (!judge(2, 4)) break;
                            tmp.matrix[3][4] = sum - sumallc[4] - tmp.matrix[2][4];
                            if (!condit(tmp.matrix[3][4]) || !judge(3, 4)) continue;
                            if (!v[trans(4, 2)]) continue;
                            adds(3, 4, 1);
                            adds(2, 4, 1);
                            REP(tmp.matrix[4][3], 1, 10)
                            {
                                if (tmp.matrix[4][3] % 2 == 0 || tmp.matrix[4][3] == 5) continue;
                                if (!judge(4, 3)) break;
                                adds(4, 3, 1);
                                REP(tmp.matrix[0][3], 1, 10)
                                {
                                    if (!judge(0, 3)) break;
                                    tmp.matrix[2][3] = sum - sumallc[3] - tmp.matrix[0][3];
                                    if (!condit(tmp.matrix[2][3]) || !judge(2, 3)) continue;
                                    if (!v[trans(3, 2)]) continue;
                                    adds(0, 3, 1);
                                    adds(2, 3, 1);
                                    REP(tmp.matrix[4][2], 1, 10)
                                    {
                                        if (tmp.matrix[4][2] % 2 == 0 || tmp.matrix[4][2] == 5) continue;
                                        if (!judge(4, 2)) break;
                                        adds(4, 2, 1);
                                        REP(tmp.matrix[3][2], 0, 10)
                                        {
                                            if (!judge(3, 2)) break;
                                            adds(3, 2, 1);
                                            REP(tmp.matrix[0][2], 1, 10)
                                            {
                                                if (!judge(0, 2)) break;
                                                tmp.matrix[1][2] = sum - sumallc[2] - tmp.matrix[0][2];
                                                if (!condit(tmp.matrix[1][2]) || !judge(1, 2) || !v[trans(2, 2)]) continue;
                                                tmp.matrix[0][1] = sum - sumallr[0] - tmp.matrix[0][2];
                                                if (tmp.matrix[0][1] == 0) continue;
                                                if (!condit(tmp.matrix[0][1]) || !judge(0, 1) || !v[trans(0, 1)]) continue;
                                                tmp.matrix[4][1] = sum - sumallr[4];
                                                if (!condit(tmp.matrix[4][1]) || !judge(4, 1) || !v[trans(4, 1)]) continue;
                                                tmp.matrix[2][1] = sum - sumallc[1] - tmp.matrix[0][1] - tmp.matrix[4][1];
                                                if (!condit(tmp.matrix[2][1]) || !judge(2, 1) || !v[trans(1, 2)]) continue;
                                                tmp.matrix[1][0] = sum - sumallr[1] - tmp.matrix[1][2];
                                                if (tmp.matrix[1][0] == 0) continue;
                                                if (!condit(tmp.matrix[1][0]) || !judge(1, 0) || !v[trans(1, 1)]) continue;
                                                tmp.matrix[2][0] = sum - sumallr[2] - tmp.matrix[2][1];
                                                if (tmp.matrix[2][0] == 0) continue;
                                                if (!condit(tmp.matrix[2][0]) || !judge(2, 0) || !v[trans(2, 1)]) continue;
                                                if (sumallc[0] + tmp.matrix[1][0] + tmp.matrix[2][0] != sumallr[3]) continue;
                                                tmp.matrix[3][0] = sum - sumallr[3];
                                                if (tmp.matrix[3][0] == 0) continue;
                                                if (!condit(tmp.matrix[3][0]) || !v[trans(0, 2)] || !v[trans(3, 1)]) continue;
                                                ans[anslen++] = tmp;
                                            }
                                            adds(3, 2, -1);
                                        }
                                        adds(4, 2, -1);
                                    }
                                    adds(0, 3, -1);
                                    adds(2, 3, -1);
                                }
                                adds(4, 3, -1);
                            }
                            adds(3, 4, -1);
                            adds(2, 4, -1);
                        }
                        adds(1, 4, -1);
                    }
                    adds(4, 0, -1);
                    adds(3, 1, -1);
                }
                adds(1, 3, -1);
            }
            adds(0, 4, -1);
        }
    }
    sort(ans, ans + anslen);
    for (int k = 0; k < anslen; ++k)
    {
        if (k != 0) printf("\n");
        for (int i = 0; i < 5; ++i)
        {
            for (int j = 0; j < 5; ++j)
                printf("%d", ans[k].matrix[i][j]);
            printf("\n");
        }
    }
    return 0;
}
时间: 2024-10-31 20:00:59

[USACO 6.4.1] The Primes的相关文章

USACO 6.4 The Primes

The PrimesIOI'94 In the square below, each row, each column and the two diagonals can be read as a five digit prime number. The rows are read from left to right. The columns are read from top to bottom. Both diagonals are read from left to right. +--

算法竞赛入门经典+挑战编程+USACO

下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发.   一.UVaOJ http://uva.onlinejudge.org  西班牙Valladolid大学的程序在线评测系统,是历史最悠久.最著名的OJ.   二.<算法竞赛入门经典> 刘汝佳  (UVaOJ  351道题)  以下部分内容摘自:http://sdkdacm.5d6d.com/thread-6-1-1.html   "AO

(Step1-500题)UVaOJ+算法竞赛入门经典+挑战编程+USACO

下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发. 一.UVaOJ http://uva.onlinejudge.org 西班牙Valladolid大学的程序在线评测系统,是历史最悠久.最著名的OJ. 二.<算法竞赛入门经典> 刘汝佳  (UVaOJ  351道题)  以下部分内容摘自:http://sdkdacm.5d6d.com/thread-6-1-1.html “AOAPC I”是刘汝佳(大

COGS 696. [IOI1996][USACO 2.3] 最长前缀

★   输入文件:prefix.in   输出文件:prefix.out   简单对比时间限制:1 s   内存限制:128 MB 描述 USACO 2.3.1 IOI96 在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的.生物学家对于把长的序列分解成较短的序列(即元素)很感兴趣. 如果一个集合 P 中的元素可以通过串联(元素可以重复使用,相当于 Pascal 中的 “+” 运算符)组成一个序列 S ,那么我们认为序列 S 可以分解为 P 中的元素.元素不一定要全部出现(如下例中B

[LeetCode]Count Primes

题目:Count Primes 统计1-n的素数的个数. 思路1: 通常的思想就是遍历(0,n)范围内的所有数,对每个数i再遍历(0,sqrt(i)),每个除一遍来判断是否为素数,这样时间复杂度为O(n*sqrt(n)). 具体实现不在贴代码,过程很简单,两重循环就可以解决.但是效率很差,n较大时甚至会花几分钟才能跑完. 思路2: 用埃拉特斯特尼筛法的方法来求素数,时间复杂度可以达到O(nloglogn). 首先开一个大小为n的数组prime[],从2开始循环,找到一个质数后开始筛选出所有非素数

projecteuler Summation of primes

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. Find the sum of all the primes below two million. 译文: 10以下的素数之和为17,求出2000000以下的素数之和. ======================= 第一次code: 1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(

USACO prefix TrieTree + DP

/* ID:kevin_s1 PROG:prefix LANG:C++ */ #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <vector> #include <map> #include <set> #include <algorithm> #include <cstdlib>

【USACO 1.3.4】牛式

[題目描述 ] 下面是一个乘法竖式,如果用我们给定的那n个数字来取代*,可以使式子成立的话,我们就叫这个式子牛式. * * * x * * ---------- * * * * * * ---------- * * * * 数字只能取代*,当然第一位不能为0,况且给定的数字里不包括0. 注意一下在美国的学校中教的"部分乘积",第一部分乘积是第二个数的个位和第一个数的积,第二部分乘积是第二个数的十位和第一个数的乘积. 写一个程序找出所有的牛式. [格式] INPUT FORMAT: (f

USACO Chapter 1 Section 1.1

USACO的题解和翻译已经很多了... 我只是把自己刷的代码保存一下. 1.PROB Your Ride Is Here 1 /* 2 ID:xiekeyi1 3 PROG:ride 4 LANG:C++ 5 */ 6 7 #include<bits/stdc++.h> 8 using namespace std ; 9 10 int main() 11 { 12 freopen("ride.in","r",stdin); 13 freopen(&quo