CodeForces - 271B Prime Matrix

You've got an n × m matrix. The matrix consists of integers. In one move, you can apply a single transformation to the matrix: choose an arbitrary element of the matrix and increase it by 1. Each element can be increased an arbitrary number of times.

You are really curious about prime numbers. Let us remind you that a prime number is a positive integer that has exactly two distinct positive integer divisors: itself and number one. For example, numbers 2, 3, 5 are prime and numbers 1, 4, 6 are not.

A matrix is prime if at least one of the two following conditions fulfills:

  • the matrix has a row with prime numbers only;
  • the matrix has a column with prime numbers only;

Your task is to count the minimum number of moves needed to get a prime matrix from the one you've got.

Input

The first line contains two integers n, m (1 ≤ n, m ≤ 500) — the number of rows and columns in the matrix, correspondingly.

Each of the following n lines contains m integers — the initial matrix. All matrix elements are positive integers. All numbers in the initial matrix do not exceed 105.

The numbers in the lines are separated by single spaces.

Output

Print a single integer — the minimum number of moves needed to get a prime matrix from the one you've got. If you've got a prime matrix, print 0.

Example
Input
3 3
1 2 3
5 6 1
4 4 1
Output
1
Input
2 3
4 8 8
9 2 9
Output
3
Input
2 2
1 3
4 2
Output
0

 【题解】 这题打眼一看好像不太好做,矩阵也比较特别,我当时刚开始也是懵比的,直接跳过去了,还以为是个数学题,到后来细细读题才发现很简单,题意就是说给你一个矩阵,现在矩阵里有的数是素数,有的不是,现在要把它构造成一个素数矩阵,(有一行全为素数或者有一列全为素数),问你最少的操作数(操作数就是可以改使矩阵某个位置的数值+1,当然加完还可以再加),最后构成这个素数矩阵,

 仔细观察的话,这个题给的数据是很弱的,所以完全可以暴力,我的做法是,先素筛打表,然后横向查找,每行从左往右扫,遇到是素数的就跳过,不是素数的就给它加1,一直加,直到它成为素数为止(用一个数组来保存每行加了多少个1),然后继续往下扫,直到一行结束,开始下一行。

 横向扫完,把保存的数的最小值找出来,意思就是横向构成素数矩阵的最少操作数,然后开始纵向扫,和刚才一样,保存每列1的个数,最后找出纵向最小操作数,和横向的相比,输出最小操作数即可。

 希望我表达的你能理解,文笔不好,勿怪哈。。

 【AC代码】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int m,n,ans;
int prime[N];
int a[505][505],b[505][505];
void primee()
{
    memset(prime,0,sizeof(prime));
    prime[0]=prime[1]=1;
    for(int i=2;i<=100005;i++)
    {
        for(int j=i+i;j<=100005;j+=i)
            prime[j]=1;
    }
}

int min(int x,int y)
{
    return x>y?y:x;
}

int main()
{
    primee();
    while(~scanf("%d%d",&m,&n))
    {
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&a[i][j]);
                b[i][j]=a[i][j];
            }

        ans=1e7;
        for(int i=1;i<=m;i++)
        {
            int sum=0;
            for(int j=1;j<=n;j++)
            {
                while(prime[a[i][j]])
                {
                    sum++;
                    a[i][j]++;
                }
            }
            ans=min(ans,sum);
        }

        for(int i=1;i<=n;i++)
        {
            int sum=0;
            for(int j=1;j<=m;++j)
            {
                while(prime[b[j][i]])
                {
                    sum++;
                    b[j][i]++;
                }
            }
            ans=min(sum,ans);
        }

        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值