agc027D Modulu Matrix

agc027D Modulu Matrix

  • 构造一个 n ∗ n n*n nn的矩阵 a a a,满足没有两个元素相等, a i , j ≤ 1 e 15 a_{i,j}\le1e15 ai,j1e15

  • 对于所有相邻的格子值为 x , y x,y x,y,满足 m a x ( x , y ) % m i n ( x , y ) max(x,y)\%min(x,y) max(x,y)%min(x,y)全部为某一个固定的值 m m m

  • n ≤ 500 n\le500 n500

Solution

  • 对于这一类构造题,可以先思考一种简单的能够得到答案的通解,我们寻求的方法应该是简单、普遍的(有的时候需要一点分类讨论),然后再进行一些转化来优化构造的答案模型。一般来说不会有很复杂的模型,主要要培养构造的感觉。

  • 注意到影响是相邻的,我们可以黑白染色(二分图),确定所有白点的数值,那么可以钦定每一个黑点的值是 l c m ( a x ) + 1 ( x 是 周 围 的 白 点 ) lcm(a_x)+1(x是周围的白点) lcm(ax)+1(x).

  • 但是我们怎么保证不重复呢?

  • 我们不妨假设所有白色点全部选质数,这样任意四个白点的乘积都不一样(可能需要对2特判)。

  • 如果直接搞 n 2 n^2 n2个素数是不能满足1e15的,注意到我们求的是lcm,我们可以适当放一些重复的元素,也就是说,把每一个格子表示成两个素数的乘积。

  • 只需要按照对角线乘同一个素数,两种对角线分别乘即可。

  • 这样构造是不会超过1e15的。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define maxn 505
#define maxm 5000005
#define ll long long 
using namespace std;

int n,i,j,k;
int tot,pri[maxm],bz[maxm];
ll a[maxn][maxn];

void getpri(){
    
    
	for(int i=2;i<maxm;i++){
    
    
		if (!bz[i]) pri[++tot]=i;
		for(int j=1;j<=tot&&i*pri[j]<maxm;j++){
    
    
			bz[i*pri[j]]=1;
			if (i%pri[j]==0) break;
		}
	}
}

ll gcd(ll x,ll y){
    
    return (x%y==0)?y:gcd(y,x%y);}
ll lcm(ll x,ll y){
    
    return x/gcd(x,y)*y;}

ll Lcm(ll a,ll b,ll c,ll d){
    
    
	ll x=1;
	if (a) x=lcm(x,a);
	if (b) x=lcm(x,b);
	if (c) x=lcm(x,c);
	if (d) x=lcm(x,d);
	return x;
}

int main(){
    
    
	freopen("ceshi.in","r",stdin);
//	freopen("ceshi.out","w",stdout);
	scanf("%d",&n),getpri(),k=0;
	if (n==2) printf("5 4\n2 3\n"),exit(0);
	for(i=1;i<=n;i++) for(j=1;j<=n;j++) a[i][j]=1;
	for(i=1;i<=n;i++) for(j=1;j<=n;j++) if ((i+j)%2==0) a[i][j]*=pri[(i+j)/2];
	for(i=1;i<=n;i++) for(j=1;j<=n;j++) if ((i+j)%2==0) a[i][j]*=pri[(i-j+n-(n&1))/2+n];
	for(i=1;i<=n;i++) for(j=1;j<=n;j++) if ((i+j)%2)
		a[i][j]=Lcm(a[i-1][j],a[i][j-1],a[i+1][j],a[i][j+1])+1;
	for(i=1;i<=n;i++,printf("\n")) for(j=1;j<=n;j++) printf("%lld ",a[i][j]);
}

猜你喜欢

转载自blog.csdn.net/qq_43649416/article/details/109105362
今日推荐