zoukankan      html  css  js  c++  java
  • 【hiho一下 第146周】子矩阵求和

    【题目链接】:http://hihocoder.com/contest/hiho146/problem/1

    【题意】

    【题解】

    设s[i][j]表示左上角的坐标为(i,j)的n*m的矩阵的和;
    有s[i][j]=s[i-1][j-1]+n*m;
    不信自己看;
    而且
    对于i>=max(n,m)
    s[i][j]=s[i+1][j];
    对于j>=max(n,m)
    s[i][j]=s[i][j+1];
    而每一行从左到右的元素和;
    每一列从上刀下的元素的和是有规律的;
    就是前x个数是等差,后面全都相等;
    然后根据这个
    我们只要算出
    s[1][1..max(n,m)]
    和s[1..max(n,m)][1]
    然后算出这2*max(n,m)个对角线上的各个位置作为左上角的矩阵的和就好;
    当然不能强算了;
    根据
    s[i][j]=s[i-1][j-1]+n*m;
    我们知道
    s[i][j]之后;
    相当于要求最小的x
    使得
    (s[i][j]+x*n*m%k)==0
    这里我们可以预处理出最小的使得x*n*m%k==t的x;
    记录下每个t对应的x就好;(当然有一些t可能没办法得到);
    这样根据s[1][1..max(n,m)]和s[1..max(n,m)][1]算出每个对角线上有没有可能有有符合要求的点;
    每次往下走的时候只会改变一行或一列的和;
    所以可以做到O(1)算出来;

    【Number Of WA

    17

    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ms(x,y) memset(x,y,sizeof x)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    const int N = 110;
    const int K = 1e6+100;
    
    int n,m,k,need[K],px,py;
    
    void pre()
    {
        ms(need,-1);
        LL now = 0;int x = 0;
        while (need[now]==-1)
        {
            need[now] = x;
            now = (now+1LL*n*m)%k;
            x++;
        }
    }
    
    int get_sum(int idx,int len)
    {
        if (len<=idx)
            return  (1LL*(1+len)*len/2)%k;
        else
            return (1LL*(1+idx)*idx/2 + 1LL*(len-idx)*idx)%k;
    }
    
    void gengxin(int x,int y)
    {
        if (px==-1 && py==-1)
        {
            px = x,py = y;
            return;
        }
        if (x+y<px+py)
        {
            px = x,py = y;
        }
        else
            if (x+y==px+py && x<px)
            {
                px = x,py = y;
            }
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        ios::sync_with_stdio(false);
        int Q;
        cin >> Q;
        while (Q--)
        {
            px=-1,py=-1;
            cin >> n >> m >> k;
            pre();
            //左上角n行m列的矩阵和
            LL sum = 0,tsum;
            rep1(i,1,m)
                sum=(sum+get_sum(i,n))%k;//相当于加上第i列的n行元素
            tsum = sum;
            int ma = max(m,n);
            rep1(nowy,1,ma)
            {
                int t = (k-sum)%k;
                if (need[t]!=-1)
                    gengxin(1+need[t],nowy+need[t]);
                sum=(sum-get_sum(nowy,n)+k+get_sum(nowy+m,n))%k;
            }
            sum = tsum;
            rep1(nowx,1,ma)
            {
                int t = (k-sum)%k;
                if (need[t]!=-1)
                {
                    int x = nowx+need[t],y = 1+need[t];
                    gengxin(x,y);
                }
                sum=(sum-get_sum(nowx,m)+k+get_sum(nowx+n,m))%k;
            }
            if (px==-1)
                cout <<-1<<endl;
            else
                cout <<px <<' '<<py<<endl;
        }
        //printf("
    %.2lf sec 
    ", (double)clock() / CLOCKS_PER_SEC);
        return 0;
    }
    
  • 相关阅读:
    luogu1210 回文检测
    luogu2420 让我们异或吧
    luogu4151 最大XOR和路径
    线性基
    博弈论(扯淡)
    矩阵求逆 模板
    luogu2513 逆序对数列
    洛谷4316 绿豆蛙的归宿(DAG递推/概率dp)
    1898: [Zjoi2005]Swamp 沼泽鳄鱼
    矩阵
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626413.html
Copyright © 2011-2022 走看看