• 【Atcoder】AGC 016 C


    【题意】给定大矩阵的边长H和W,给每格填数(<=|10^9|),要求大矩形总和为正数,而每个h*w的小矩形总和为负数,求构造方式。

    【算法】数学

    【题解】结论题。

    ★当h|H&&w|W(H是w的倍数,W是w的倍数)时,每个小矩阵之和加起来翻倍刚好成为大矩阵,无解。

    当不为倍数时,显然会有多余的行列,我们尝试一种构造方式使多余的行列起作用。

    1.从0计数,在h倍数行全部填正数1000(h-1)-1,在其他行全部填负数-1000(行是倍数时换成列,同理)。

    这样构造,在h行范围内只有一行正数,每列之和都是-1。而论总和而言,多余行也有一行正数,小矩阵不满,所以每列至少多出1000-500,解决问题。

    2.另一种构造方式,从1计数,在每个h*w倍数处填-1000*(h*w-1)-1,其它地方填1000,这样只要有一多余行列,多的若干个1000就可以将矩阵变成正数。

    关键在第一个倍数无解的结论,有解时只要利用多余行列构造即可。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int read()
    {
        char c;int s=0,t=1;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    /*------------------------------------------------------------*/
    const int inf=0x3f3f3f3f;
     
    int N,M,n,m;
     
    int main()
    {
        scanf("%d%d%d%d",&N,&M,&n,&m);
        if(N%n==0&&M%m==0){printf("No");return 0;}
        printf("Yes
    ");
        for(int i=1;i<=N;i++){
            for(int j=1;j<=M;j++)
                printf("%d ",i%n||j%m?1100:-1100*(n*m-1)-1);
            printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    HTTP处理程序介绍
    c# Enum获取name,value和description
    如何成为优秀的软件人才
    关于系统设计分层
    从DLL中加载启动窗体
    摩斯密码
    休息下
    关于博文转载
    整合TextBox与Label 创建新控件EFLabelText
    ProC连接Oracle
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7358734.html
Copyright © 2020-2023  润新知