• USACO6.4-The Primes


    The Primes
    IOI'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.

    +---+---+---+---+---+
    | 1 | 1 | 3 | 5 | 1 |
    +---+---+---+---+---+
    | 3 | 3 | 2 | 0 | 3 |
    +---+---+---+---+---+
    | 3 | 0 | 3 | 2 | 3 |
    +---+---+---+---+---+
    | 1 | 4 | 0 | 3 | 3 |
    +---+---+---+---+---+
    | 3 | 3 | 3 | 1 | 1 |
    +---+---+---+---+---+ 
    
    • The prime numbers' digits must sum to the same number.
    • The digit in the top left-hand corner of the square is pre-determined (1 in the example).
    • A prime number may be used more than once in the same square.
    • If there are several solutions, all must be presented (sorted in numerical order as if the 25 digits were all one long number).
    • A five digit prime number cannot begin with a zero (e.g., 00003 is NOT a five digit prime number).

    PROGRAM NAME: prime3

    INPUT FORMAT

    A single line with two space-separated integers: the sum of the digits and the digit in the upper left hand corner of the square.

    SAMPLE INPUT (file prime3.in)

    11 1
    

    OUTPUT FORMAT

    Five lines of five characters each for each solution found, where each line in turn consists of a five digit prime number. Print a blank line between solutions. If there are no prime squares for the input data, output a single line containing "NONE".

    SAMPLE OUTPUT (file prime3.out)

    The above example has 3 solutions.

    11351
    14033
    30323
    53201
    13313
    
    11351
    33203
    30323
    14033
    33311
    
    13313
    13043
    32303
    50231
    13331
    

    题目大意:给出一个5*5的正方形和左上角的一个数字,要求每一行每一列每一对角线上的数字的和都等于输入的数,并且组成的五位数为质数,输出所有可能的5*5正方形。

    算法:这是一道很麻烦的暴力题,朴素的枚举必定会超时,这时候需要调换枚举顺序,以及根据枚举的五位数的位置尽可能排除不可能的情况再枚举,要优化的地方还是比较多的,详见代码。

      1 #include <iostream>
      2 #include <memory.h>
      3 #include <stdio.h>
      4 #include <vector>
      5 #include <string>
      6 #include <algorithm>
      7 using namespace std;
      8 #define MAXN 100000
      9 #define R 0
     10 #define C 1
     11 
     12 
     13 void output(string str)
     14 {
     15     for(int i=0; i<str.length(); i++)
     16     {
     17         printf("%c",str[i]);
     18         if(i%5==4)
     19             printf("
    ");
     20     }
     21 }
     22 
     23 int getDigSum(int x)
     24 {
     25     int sum=0;
     26     while(x!=0)
     27     {
     28         sum+=x%10;
     29         x/=10;
     30     }
     31     return sum;
     32 }
     33 
     34 bool allDigOdd(int x)
     35 {
     36     while(x!=0)
     37     {
     38         int dig=x%10;
     39         if(dig%2==0)
     40             return false;
     41         x/=10;
     42     }
     43     return true;
     44 }
     45 
     46 bool allNoZero(int x)
     47 {
     48     while(x!=0)
     49     {
     50         int dig=x%10;
     51         if(dig==0)
     52             return false;
     53         x/=10;
     54     }
     55     return true;
     56 }
     57 
     58 int isPrime[MAXN+10],primeDig[MAXN+10][5];
     59 
     60 int a[5][5]= {0},goalSum=0,st;
     61 vector<int> primelist[100]; // 以d[ij]表示以i开头,j结尾的字符串
     62 vector<int> primelistMid[1000]; // 以d[ijk]表示以i开头,j为百位,k结尾的字符串
     63 vector<int> primelistOdd[100]; // 各位上的数都为奇数
     64 vector<int> primelistnozero[100]; // 各位上都没有0
     65 vector<string> res;
     66 
     67 int isprime(int type,int num)
     68 {
     69 
     70     int sum=0;
     71     if(type==R)
     72     {
     73         for(int i=0; i<5; i++)
     74             sum=sum*10+a[num][i];
     75     }
     76     else
     77     {
     78         for(int i=0; i<5; i++)
     79             sum=sum*10+a[i][num];
     80     }
     81     return isPrime[sum];
     82 }
     83 
     84 void add()
     85 {
     86     string str;
     87     for(int i=0; i<5; i++)
     88         for(int j=0; j<5; j++)
     89         {
     90             str+='0'+a[i][j];
     91         }
     92     res.push_back(str);
     93 }
     94 
     95 void initA()
     96 {
     97     for(int i=0; i<5; i++)
     98         for(int j=0; j<5; j++)
     99             a[i][j]=100;
    100 }
    101 
    102 int main()
    103 {
    104     freopen("prime3.in","r",stdin);
    105     freopen("prime3.out","w",stdout);
    106 
    107     initA();
    108 
    109     // 求素数表
    110     memset(isPrime,-1,sizeof isPrime);
    111     for(int i=2; i<=MAXN; i++)
    112         if(isPrime[i])
    113             for(long long j=(long long)i*i; j<=MAXN; j+=i)
    114                 isPrime[j]=false;
    115 
    116 
    117     cin>>goalSum>>st;
    118 
    119     for(int i=10000; i<MAXN; i++)
    120         if(isPrime[i] && getDigSum(i)!=goalSum)
    121             isPrime[i]=0;
    122 
    123     for(int i=10000; i<MAXN; i++)
    124         if(isPrime[i])
    125         {
    126             int x=i;
    127             for(int j=0; j<5; j++)
    128             {
    129                 primeDig[i][4-j]=x%10;
    130                 x/=10;
    131             }
    132             primelist[i/10000*10+i%10].push_back(i);
    133             primelistMid[i/10000*100+(i%1000)/100*10+i%10].push_back(i);
    134         }
    135 
    136     // 各位上都为奇数
    137     for(int i=10000; i<MAXN; i++)
    138         if(isPrime[i] && allDigOdd(i))
    139             primelistOdd[i/10000*10+i%10].push_back(i);
    140 
    141     // 各位上都为非0
    142     for(int i=10000; i<MAXN; i++)
    143         if(isPrime[i] && allNoZero(i))
    144             primelistnozero[i/10000*10+i%10].push_back(i);
    145 
    146     bool found=false;
    147 
    148     a[0][0]=st;
    149     // 枚举 先是右下方数字
    150     for(a[4][4]=1; a[4][4]<=9; a[4][4]+=2)
    151     {
    152         // 枚举左下方数字
    153         for(a[4][0]=1; a[4][0]<=9; a[4][0]+=2)
    154         {
    155             // 枚举右上方数字
    156             for(a[0][4]=1; a[0][4]<=9; a[0][4]+=2)
    157             {
    158                 //填充左边质数
    159                 for(int i=0; i<primelistnozero[st*10+a[4][0]].size(); i++)
    160                 {
    161                     for(int j=0; j<5; j++)
    162                         a[j][0]=primeDig[primelistnozero[st*10+a[4][0]][i]][j];
    163 
    164                     // 填充上边质数
    165                     for(int ii=0; ii<primelistnozero[st*10+a[0][4]].size(); ii++)
    166                     {
    167                         for(int j=0; j<5; j++)
    168                             a[0][j]=primeDig[primelistnozero[st*10+a[0][4]][ii]][j];
    169 
    170 
    171                         // 填充下边质数
    172                         for(int iii=0; iii<primelistOdd[a[4][0]*10+a[4][4]].size(); iii++)
    173                         {
    174                             for(int j=0; j<5; j++)
    175                                 a[4][j]=primeDig[primelistOdd[a[4][0]*10+a[4][4]][iii]][j];
    176 
    177 
    178                             //填充右边质数
    179                             for(int iiii=0; iiii<primelistOdd[a[0][4]*10+a[4][4]].size(); iiii++)
    180                             {
    181                                 for(int j=0; j<5; j++)
    182                                     a[j][4]=primeDig[primelistOdd[a[0][4]*10+a[4][4]][iiii]][j];
    183 
    184 
    185                                 // 填充中间一点
    186                                 for(a[2][2]=0; a[2][2]<=9; a[2][2]++)
    187                                 {
    188 
    189                                     // 填充主对角线
    190                                     for(int k=0; k<primelistMid[st*100+a[2][2]*10+a[4][4]].size(); k++)
    191                                     {
    192                                         a[1][1]=primeDig[primelistMid[st*100+a[2][2]*10+a[4][4]][k]][1];
    193                                         a[3][3]=primeDig[primelistMid[st*100+a[2][2]*10+a[4][4]][k]][3];
    194 
    195                                         // 填充辅对角线
    196                                         for(int l=0; l<primelistMid[a[4][0]*100+a[2][2]*10+a[0][4]].size(); l++)
    197                                         {
    198                                             a[3][1]=primeDig[primelistMid[a[4][0]*100+a[2][2]*10+a[0][4]][l]][1];
    199                                             a[1][3]=primeDig[primelistMid[a[4][0]*100+a[2][2]*10+a[0][4]][l]][3];
    200 
    201                                             int a12=goalSum-(a[1][0]+a[1][1]+a[1][3]+a[1][4]);
    202                                             int a21=goalSum-(a[0][1]+a[1][1]+a[3][1]+a[4][1]);
    203                                             int a23=goalSum-(a[0][3]+a[1][3]+a[3][3]+a[4][3]);
    204                                             int a32=goalSum-(a[3][0]+a[3][1]+a[3][3]+a[3][4]);
    205                                             a[1][2]=a12;
    206                                             a[2][1]=a21;
    207                                             a[2][3]=a23;
    208                                             a[3][2]=a32;
    209                                             if(a12>=0 && a12<10 && a21>=0 && a21<10 && a23>=0 && a23<10 && a32>=0 && a32<10
    210                                                     && isprime(R,1) && isprime(R,2) && isprime(R,3)
    211                                                     && isprime(C,1) && isprime(C,2) && isprime(C,3))
    212                                             {
    213                                                 found=true;
    214                                                 add();
    215                                             }
    216                                         }
    217 
    218                                     }
    219                                 }
    220 
    221                             }
    222                         }
    223                     }
    224                 }
    225             }
    226         }
    227     }
    228 
    229     sort(res.begin(),res.end());
    230     bool first=true;
    231     for(int i=0; i<res.size(); i++)
    232     {
    233         if(!first)
    234         {
    235             cout<<endl;
    236         }
    237         first=false;
    238         output(res[i]);
    239     }
    240 
    241     if(!found)
    242         printf("NONE
    ");
    243     return 0;
    244 }
    
    
  • 相关阅读:
    修改apache的默认访问目录
    禁止浏览器直接访问php文件
    使用Apache Bench进行压力测试
    关于mysql(或MariaDB)中的用户账号格式
    单表查询
    CSS设计指南之一 HTML标记与文档结构
    SQL SERVER技术内幕之10 可编程对象
    SQL SERVER技术内幕之10 事务并发
    观察者模式
    中介者模式
  • 原文地址:https://www.cnblogs.com/oneshot/p/4121954.html
Copyright © 2020-2023  润新知