ACcoders Problem 2057 题解

题意

现有一个未被填充的 5 × 5 5\times 5 5×5 的方阵,给出左上角的值,以及每行每列和两个对角线的和且需要满足所构成的 5 5 5 位数为质数,问所有的方阵填法是什么(字典序从小到大)?

思路

因为每行每列两个对角线必须是一个质数,所以我们可以先将在 [ 10000 , 99999 ] [10000,99999] [10000,99999] 之间的质数先都筛出来。然后考虑暴力,每个点可能是的数都在 0 0 0 9 9 9 之间(最高位不为 0 0 0),那么时间复杂度即为 O ( 9 25 ) O(9^{25}) O(925) 绝对会超时。

剪枝1:性质剪枝 在区间 [ 10000 , 99999 ] [10000,99999] [10000,99999] 之间,所有质数的结尾必定不是偶数且不为 5 5 5,所以我们可以构造出来 l a s t last last 数组,数组中的元素即为末尾数字 1 , 3 , 5 , 7 1,3,5,7 1,3,5,7,当我们枚举末尾数字时就可以只枚举 4 4 4 次了。

剪枝2:可行性剪枝 因为当我们已经枚举了一行一列或一个对角线当中的 4 4 4 个数字时,第 5 5 5 个数字已经可以被算出来了,这样可以减少第五个数字的循环,大大的节省了时间。

剪枝3:顺序剪枝 根据上面所用到的剪枝,我们可以找到一种合适的顺序去尽可能的使枚举次数少。因为末尾的数字只需要枚举四次,所以我们优先枚举末尾的数字,尽可能少的枚举中间数字。

每次由其他 4 4 4 个数字计算出来的第五个数字如果小于 0 0 0 就直接退出(开头小于等于 0 0 0),因为是正序枚举,成单调递增,再枚举绝对也小于 0 0 0。如果大于 9 9 9 就这跳过这次,和之前同理。如果同时构成了两个数字第二次全部跳过,因为之前有另外一个数字,再枚举它也有可能符合条件。如果不在我们提前筛出来的质数表中,就直接跳过。

每次枚举出来一个方阵,就将其存入一个字符串数组当中,全部枚举之后从小到大排序(字典序从小到大),最后直接输出答案。

代码

#include<bits/stdc++.h>
using namespace std;
int pri[1000001],cnt;
bool ispri[1000001];
int f[6][6],last[]={1,3,7,9};
string ans[1000001];
int n,k,tot;
bool check(int a,int b,int c,int d,int e){
    return ispri[a*10000+b*1000+c*100+d*10+e];
}
void getprime()
{
    memset(ispri,1,sizeof(ispri));
    ispri[1]=0;
    for(int i=2;i<=100000;i++)
        if(ispri[i]) 
            for(int j=i;j<=100000/i;j++)
                ispri[i*j]=0;
}
int main()
{
    scanf("%d %d",&n,&k);
    f[1][1]=k;getprime();
    for(int A=0;A<4;A++)
    {
        f[5][5]=last[A];
        for(int B=0;B<=9;B++)
        {
            f[4][4]=B;
            for(int C=0;C<=9;C++)
            {
                f[3][3]=C;
                f[2][2]=n-f[1][1]-f[3][3]-f[4][4]-f[5][5];
                if(f[2][2]<0) break;
                if(f[2][2]>9) continue;
                if(!check(f[1][1],f[2][2],f[3][3],f[4][4],f[5][5]))
                    continue;
                for(int D=0;D<4;D++)
                {
                    f[5][1]=last[D];
                    for(int E=0;E<4;E++)
                    {
                        f[5][2]=last[E];
                        for(int F=0;F<4;F++)
                        {
                            f[5][3]=last[F];
                            f[5][4]=n-f[5][1]-f[5][2]-f[5][3]-f[5][5];
                            if(f[5][4]<0) break;
                            if(f[5][4]>9) continue;
                            if(!check(f[5][1],f[5][2],f[5][3],f[5][4],f[5][5]))
                                continue;
                            for(int G=0;G<4;G++)
                            {
                                f[1][5]=last[G];
                                for(int H=0;H<4;H++)
                                {
                                    f[2][5]=last[H];
                                    for(int I=0;I<4;I++)
                                    {
                                        f[3][5]=last[I];
                                        f[4][5]=n-f[1][5]-f[2][5]-f[3][5]-f[5][5];
                                        if(f[4][5]<0) break;
                                        if(f[4][5]>9) continue;
                                        if(!check(f[1][5],f[2][5],f[3][5],f[4][5],f[5][5]))
                                            continue;
                                        for(int J=0;J<=9;J++)
                                        {
                                            f[4][2]=J;
                                            f[2][4]=n-f[5][1]-f[4][2]-f[3][3]-f[1][5];
                                            if(f[2][4]<0) break;
                                            if(f[2][4]>9) continue;
                                            if(!check(f[5][1],f[4][2],f[3][3],f[2][4],f[1][5]))
                                                continue;   
                                            for(int K=1;K<=9;K++)
                                            {
                                                f[1][4]=K;
                                                f[3][4]=n-f[1][4]-f[2][4]-f[4][4]-f[5][4];
                                                if(f[3][4]<0) break;
                                                if(f[3][4]>9) continue;
                                                if(!check(f[1][4],f[2][4],f[3][4],f[4][4],f[5][4]))
                                                    continue;                                   
                                                for(int L=1;L<=9;L++)
                                                {
                                                    f[1][3]=L;      
                                                    f[1][2]=n-f[1][1]-f[1][3]-f[1][4]-f[1][5];
                                                    if(f[1][2]<=0) break;
                                                    if(f[1][2]>9) continue;
                                                    if(!check(f[1][1],f[1][2],f[1][3],f[1][4],f[1][5]))
                                                        continue;   
                                                    f[3][2]=n-f[1][2]-f[2][2]-f[4][2]-f[5][2];
                                                    if(f[3][2]<0) continue;
                                                    if(f[3][2]>9) continue;
                                                    if(!check(f[1][2],f[2][2],f[3][2],f[4][2],f[5][2]))
                                                        continue;                   
                                                    for(int M=1;M<=9;M++)
                                                    {
                                                        f[2][1]=M;
                                                        f[2][3]=n-f[2][1]-f[2][2]-f[2][4]-f[2][5];
                                                        if(f[2][3]<0) break;
                                                        if(f[2][3]>9) continue;
                                                        if(!check(f[2][1],f[2][2],f[2][3],f[2][4],f[2][5]))
                                                            continue;   
                                                        f[4][3]=n-f[1][3]-f[2][3]-f[3][3]-f[5][3];
                                                        if(f[4][3]<0) continue;
                                                        if(f[4][3]>9) continue;
                                                        if(!check(f[1][3],f[2][3],f[3][3],f[4][3],f[5][3]))
                                                            continue;   
                                                        f[4][1]=n-f[4][2]-f[4][3]-f[4][4]-f[4][5];
                                                        if(f[4][1]<=0) continue;
                                                        if(f[4][1]>9) continue;
                                                        if(!check(f[4][1],f[4][2],f[4][3],f[4][4],f[4][5]))
                                                            continue;                               
                                                        f[3][1]=n-f[1][1]-f[2][1]-f[4][1]-f[5][1];
                                                        if(f[3][1]<=0) continue;
                                                        if(f[3][1]>9) continue;
                                                        if(!check(f[1][1],f[2][1],f[3][1],f[4][1],f[5][1]))
                                                            continue;
                                                        if(!check(f[3][1],f[3][2],f[3][3],f[3][4],f[3][5]))
                                                            continue;
                                                        tot++;
                                                        for(int i=1;i<=5;i++)
                                                            for(int j=1;j<=5;j++)
                                                                ans[tot]+=f[i][j]+48;
                                                    }                   
                                                }       
                                            }                                       
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    if(!tot){puts("NONE");return 0;}
    sort(ans+1,ans+tot+1);
    for(int i=1;i<=tot;i++)
    {
        for(int j=0;j<25;j++)
        {
            printf("%c",ans[i][j]);
            if(!((j+1)%5)) puts("");
        }
        puts("");
    }   
    return 0;
}   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值