zoukankan      html  css  js  c++  java
  • tyvj 1924 七夕祭 【数学推理+数形结合】

    题在这:http://www.tyvj.cn/p/1924

    分析:
    通过简单的分析,我们可以得出:因为不能斜着交换,因此横行和竖排的交换是互不相干的。(横排交换的时候竖排没有变换)故,我们就能把横和纵分开分析,二者等价;

    二维转化成一维后,它等同于这个样子:

    老师准备了一堆糖果, 恰好n个小朋友可以分到数目一样多的糖果. 老师要n个小朋友去拿糖果, 然后围着圆桌坐好, 第1个小朋友的左边是第n个小朋友, 其他第i个小朋友左边是第i-1个小朋友. 大家坐好后, 老师发现, 有些小朋友抢了很多的糖果, 有的小朋友只得到了一点点糖果, 甚至一颗也没有L, 设第i个小朋友有ai颗糖果. 小朋友们可以选择将一些糖果给他左边的或者右边的小朋友, 通过”糖果传递”最后使得每个小朋友得到的糖果数是一样多的, 假设一颗糖果从一个小朋友传给另一个小朋友的代价是1, 问怎样传递使得所耗的总代价最小

    首先,可以很容易地判断出排或列有无解,当总摊位数 T 不能够整除排数时,no row; 当总摊位数 T 不能够整除列数时,
    no column;当两个均不能整除时,impossible。

    我们设第 i 列原本a[i]个摊位, i 列要给 i-1 列x(i)个摊位, i+1 列要给 i 列x (i+1)个摊位,算出平均下来每列应该最终为 ave 个摊位,可得:
                                                                   a[i] - x(i) + x(i+1) = ave
    就像数列一样,我们把它们列出来,找规律:

    a[1] - x(1) + x(2) = ave      ====》  x(2) = ave - a[1] + x(1) ;
    a[2] - x(2) + x(3) = ave      ====》  x(3) = ave - a[2] + x(2) ;
    a[3] - x(3) + x(4) = ave      ====》  x(4) = ave - a[3] + x(3) ;
    …… ……

    从第一个起: 我们令 a[i] - x(i) = c[i];
    其中:c[i] 表示前 i 个列的原本值与平均值之差的前缀和
    变形得:
    x(2) = x(1) - c[1];
    x(3) = x(1) - c[2];
    x(4) = x(1) - c[3];
    …… ……
    于是为了让x(1)+x(2)+x(3)+……+x(i)最小,相当于在数轴上取一点x(1),使得它到c[1] , c[2] , c[3]……的距离之和最小,这显然是要取c[i]的中位数的(可自己证明)。

    下面是参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    int pai[200000]={0},lie[200000]={0};
    int n,m,T; 
    int sum_pai=0,sum_lie=0;
    int ave_pai,ave_lie;
    int ans=0;
    long long c1[200000]={0};
    long long c2[200000]={0};
    void solve()
    {
        if(!(T%n))
        {
            for (int i=1;i<=n;i++)
                c1[i]=c1[i-1]+pai[i];
            sort(c1+1,c1+n+1);
            long long mid=c1[(n+1)/2];
            for(int i=1;i<=n;i++)
                ans+=abs(c1[i]-mid);
        }
        if(!(T%m))
        {
            for(int i=1;i<=m;i++)
                c2[i]=c2[i-1]+lie[i];
            sort(c2+1,c2+m+1);
            long long mid=c2[(m+1)/2];
            for(int i=1;i<=m;i++)
                ans+=abs(c2[i]-mid);
        }
    }
    
    int main()
    {
        cin>>n>>m>>T;
        int t=T;
        while(t--)
        {
            int x,y;
            cin>>x>>y;
            pai[x]++;
            lie[y]++;
        }
        if(T%n&&T%m)
        {
            cout<<"impossible";
            return 0;
        }
        ave_pai=T/n;
        ave_lie=T/m;
        for(int i=1;i<=n;i++)
            pai[i]=pai[i]-ave_pai;
        for(int i=1;i<=m;i++)
            lie[i]=lie[i]-ave_lie;
        solve();
        if(T%n==0&&T%m==0)printf("both ");
        else if(T%n==0)printf("row ");
        else printf("column ");
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    SDU暑期集训排位(8)
    hdu1423 最长公共上升子序列
    poj2385 Apple Catching (线性dp)
    hdu5857 Median(模拟)
    hdu5858 Hard problem(求两圆相交面积)
    shuoj 1 + 2 = 3? (二分+数位dp)
    Codeforces Round #460 (Div. 2) B Perfect Number(二分+数位dp)
    hdu4734 F(x)(数位dp)
    hdu3709 Balanced Number (数位dp)
    hdu3652 B-number(数位dp)
  • 原文地址:https://www.cnblogs.com/linda-fcj/p/7206166.html
Copyright © 2011-2022 走看看