CodeForces 449A - Jzzhu and Chocolate

传送门:Jzzhu and Chocolate

题意:

  给出一个N * M的矩阵,给K个操作,每次操作可以横/竖切割矩阵,最后求K次切割之后,矩阵最小的那块面积最大是多少?

分析:

  按照题意,题目求的结果是:(最小的面积,最大是多少),那么可以想到,K次切割之后尽量使得每个块的面积相等,某些块比较大(因为不一定能平均分),那么就可以使得最小的那块面积最大了。

  然后如何切割呢?

  因为有横竖两个切割方法,那么我们可以设X为横切割数,Y为竖切割数,其中(0 <= X, Y <= K),因为最多对一个方向切割K次,最少不切割,就是0了。这个范围很重要。

  按照上面分析的, (K次切割之后尽量使得每个块的面积相等),首先只对其中一个方向来看,尽量相等,那么我们可以不管剩下不想等的了,因为肯定比其他大,就不是我们想要的最小那块,那么根据整除的性质,设最后横竖剩下的那块大小为A * B, 那么就有

  A = N / (X + 1);   (为什么是X + 1, 因为切了X次之后,就肯定有X+1份,那么求平均大小,就是除X+1咯)

  B = M / (Y + 1);

  注意,上面是整除,也可以写成:

  A = floor(N / (X + 1));

  B = floor(M / (Y + 1));

  那么得到A * B 最大,就是

  =>    A * B = floor(N / (X + 1)) * floor(M / (Y + 1)); 最大

  暂时忽略整除性质(这个很重要,但是推导公式的时候,可以先忽略,因为不会影响推导)。

  =>    A * B = N / (X + 1) * M / (Y + 1);

  要使得上面A * B 最大,那么就是 N / (X + 1) * M / (Y + 1) 最大就好了

  =>    A * B = (N * M) / ((X + 1) * (Y + 1))

  因为N, M为已知数,使得方程组最大,分子固定,那么只需要分母最小就好了。

  现在就转化成为求(X + 1) * (Y + 1)如何情况下最小。

  因为X + Y == K,这里可以看出来,横竖必须要满足可以切割K次

  而又因为假如有N个格子,最多切N - 1次,所以可以得到判定式

  =>    如果  (N - 1 + M - 1 < K)  那么最后是切不完的,结果就是 -1

  由(X + 1) * (Y + 1), X + Y == K可以得到,新的方程式是:

  =>    (X + 1) * (K - X + 1)

  设F(X)= (X + 1) * (K - X + 1) 最小,现在就是求F(X)最小的问题了,

  =>    F(X) = -X ^ 2 + K * X + K + 1 (0 <= X <= K)(0 <= X <= N)

  这个是一元二次方程组,其中K为已知(题目给了)

  最后就是求解这个方程组的最小值问题了。

  学过数学的都知道,这个方程组的开口向下

  由于X的范围是[0, K],现在要讨论K与N的关系了

  (1)    如果  K <= N - 1(为什么是N - 1, 因为如果要把一个面切成N份,只需要切N-1次就可以了),那么就是可以在N上切K次,

  由于方程式的性质(开头向下的一元二次方程),那么容易想到要使得F(X)最小,只有两个点,

  1. X == 0 这个时候F(X)跟y轴相交

  2. 因为对于X,F(X)在y轴线右边是单调递减的,所以如果要使得F(X)最小,X取最大值就可以了,所以X == K

  那么第一种情况下,X == K就是解(简单吧?)

  X == K的话,那么Y == 0 咯

  所以A * B == floor(N / (K + 1)) * floor(M / (0 + 1));

  因为现在假设的是横切K次,有可能列切K次才是最优结果,那么就做两次再对比咯

  A * B == floor(M / (K + 1)) * floor(N / (0 + 1));

  两个结果取最大值就行了。

  (2)    如果 K > N - 1,那么就要讨论如何切割了。

  还是那个方程式 F(X) = -X^2 + K * X + K + 1 (0 <= X <= K)(0 <= X <= N)

  1. X == 0 这个时候F(X)跟y轴相交

  2. 因为对于X,F(X)在y轴线右边是单调递减的,所以如果要使得F(X)最小,X取最大值就可以了,最大值就是N,但是不能切N次,所以取N - 1 (N - 1次就可以把整块切成N份了)

  那么第二种情况下,X == N - 1就是解

  X == N - 1的话,那么Y == K - (N - 1) 咯

  所以A * B == floor(N / ((N - 1) + 1)) * floor(M / ((K - (N - 1)) + 1));

  

  因为现在假设的是横切K次,有可能列切K次才是最优结果,那么就做两次再对比咯

  A * B == floor(M / ((M - 1) + 1)) * floor(N / ((K - (M - 1)) + 1));

  两个结果取最大值就行了。

代码如下:

  1 #ifndef ONLINE_JUDGE
  2 #define __DEBUG__ 0
  3 #endif
  4
  5 /*
  6  * =======================================
  7  *    FileName: code.cpp
  8  *        Desc:
  9  *      Author: vinceliang
 10  *       Email: [email protected]
 11  *    HomePage:
 12  *     Version: 0.0.1
 13  *  LastChange: 2014-07-15 12:16:49
 14  *     History:
 15  *========================================
 16  */
 17
 18
 19
 20 #ifdef __DEBUG__
 21 #define Log(...) printf(__VA_ARGS__)
 22 #else
 23 #define Log(...) //
 24 #endif
 25
 26 #include <algorithm>
 27 #include <string>
 28 #include <complex>
 29 #include <cassert>
 30 #include <memory>
 31 #include <set>
 32 #include <stack>
 33 #include <map>
 34 #include <list>
 35 #include <deque>
 36 #include <numeric>
 37 #include <cctype>
 38 #include <cstddef>
 39 #include <vector>
 40 #include <queue>
 41 #include <iostream>
 42 #include <iomanip>
 43 #include <iterator>
 44 #include <cmath>
 45 #include <cstdio>
 46 #include <cstdlib>
 47 #include <sstream>
 48 #include <fstream>
 49 #include <ctime>
 50 #include <cstring>
 51 #include <functional>
 52 #include <bitset>
 53
 54 using namespace std;
 55
 56 #if defined(_MSC_VER) || defined(__BORLANDC__)
 57 typedef unsigned __int64 uint64;
 58 typedef unsigned __int64 ULL;
 59 typedef signed __int64 int64;
 60 typedef signed __int64 LL;
 61 #else
 62 typedef unsigned long long uint64;
 63 typedef unsigned long long ULL;
 64 typedef signed long long int64;
 65 typedef signed long long LL;
 66 #endif
 67
 68 typedef vector<int> VI;
 69 typedef vector<string> VS;
 70 typedef pair<int, int> PII;
 71 typedef pair<int64, int64> PLL;
 72 typedef vector<int64> VL;
 73
 74 #define pb push_back
 75 #define pob pop_back
 76 #define mp make_pair
 77 #define fi first
 78 #define se second
 79
 80 #define PII pair< int,int >
 81 #define PSS pair< string,string >
 82 #define PDD pair< double,double >
 83 #define PLL pair< LL, LL >
 84
 85 #define FOR( i, a, b ) for ( int i=(a), _n=(b); i < _n; ++i )
 86 #define FORE( i, a, b ) for ( int i=(a), _n=(b); i <= _n; ++i )
 87 #define FORD( i, a, b ) for ( int i=(a), _n=(b); i >= _n; --i )
 88
 89 #define REP( i, n ) FOR( i, 0, (n) )
 90 #define REPE( i, n ) FORE( i, 1, (n) )
 91
 92 #define ALL( c ) (c).begin(), (c).end()
 93 #define SORT( c ) sort( ALL( c ) )
 94 #define LEN( s ) (int)( (s).size() )
 95 #define CLS( a ) memset( (a),0,sizeof(a) )
 96
 97 #define IOS ios::sync_with_stdio( false )
 98
 99 const double PI = 3.1415926535897932384626433832795028841971;
100 const double EPS = 1E-9;
101 const int64 INF64 = (int64)1E18;
102 const int INF = 1 << 30;
103 const int maxn = 1005;
104
105 LL fun( LL iMax, LL iMin, LL k )
106 {
107     LL Area = -1;
108     if ( iMax > k )
109     {
110         Area = ( iMax / (k + 1) ) * iMin;
111     }
112     else
113     {
114         LL leftK = k - (iMax - 1);
115         if ( iMin > leftK )
116         {
117             Area = ( iMin / ( leftK + 1 ) );
118         }
119         else
120         {
121             Area = -1;
122         }
123     }
124     return Area;
125 }
126
127 void run()
128 {
129     LL n, m, k;
130     while (  cin >> n >> m >> k )
131     {
132
133         LL Area = fun( n, m, k );
134         LL Area2 = fun( m, n, k );
135         if ( Area2 > Area ) Area = Area2;
136         cout << Area << endl;
137
138     }
139
140 }
141
142
143 int main( int argc, char **argv )
144 {
145
146 #ifndef ONLINE_JUDGE
147         freopen("in.txt", "r", stdin);
148 //      freopen("out.txt", "w", stdout);
149 #endif
150
151         time_t st = clock();
152
153         run();
154
155         Log("\n=============\n");
156         Log("Time: %.2lf sec\n", (clock() - st) / double(CLOCKS_PER_SEC));
157
158         return 0;
159
160 }
时间: 2024-10-15 16:57:51

CodeForces 449A - Jzzhu and Chocolate的相关文章

449A - Jzzhu and Chocolate 贪心

一道贪心题,尽量横着切或竖着切,实在不行在交叉切 #include<iostream> #include<stdio.h> using namespace std; int main(){ // freopen("in.txt","r",stdin); long long n,m,k; while(cin>>n>>m>>k){ if((n+m-2)<k){ printf("-1\n"

Codeforces Round #257 (Div. 2)449A - Jzzhu and Chocolate(贪心、数学)

题目链接:http://codeforces.com/problemset/problem/449/A ---------------------------------------------------------------------------------------------------------------------------------------------------------- 欢迎光临天资小屋:http://user.qzone.qq.com/593830943

Codeforces 450C:Jzzhu and Chocolate(贪心)

C. Jzzhu and Chocolate time limit per test: 1 seconds memory limit per test: 256 megabytes input: standard input output: standard output Jzzhu has a big rectangular chocolate bar that consists of \(n?×?m\) unit squares. He wants to cut this bar exact

【矩阵快速幂 】Codeforces 450B - Jzzhu and Sequences (公式转化)

[题目链接]click here~~ [题目大意] Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, please calculate fn modulo1000000007(109?+?7). [解题思路] /*A - Jzzhu and Sequences Codeforces 450B - Jzzhu and Sequences ( 矩阵快速幂 )

CodeForces 449C Jzzhu and Apples 数学+素数

这道题目晚上本来就花了很多把都××了,着实觉得自己思路没错啊,回顾一下思路,给你n个数,分成两两组合一对,分成最多组如何分,但是组合的两个数 不能互素,所以呢 偶数肯定是好的了,所以先放着,先把素数给搞定,10^5所以枚举所有包含该素数因子的数,如果刚好分组则最好,不然的话其中有偶数的踢掉一个给下面的偶数处理部分,最后再处理偶数的部分,这样肯定满足组数最多,完全没有问题,后来方法确实是没问题啊,只是代码有问题,我靠!真是脑残!,今天看到一位大牛的想法,我跟他是一样的,只是代码写搓了,后来改了又改

Codeforces449A Jzzhu and Chocolate &amp;&amp; 449B Jzzhu and Cities

CF挂0了,简直碉堡了.两道题都是正确的思路但是写残了.写个解题报告记录一下心路历程. A题问的是 一个n*m的方块的矩形上切k刀,最小的那一块最大可以是多少.不难发现如果纵向切k1刀,横向切k2刀,那么答案应该是 (n/(k1+1)) * (m/(k2+1)),除法是取整的.虽然是取整,但是不难发现其实就是要(k1+1)*(k2+1)最小,根据均值不等式,k1+k2=k(定值) k1==k2的时候(k1+1)*(k2+1)=k1*k2+k1+k2+1=k1*k2+k+1应该是取最大值,所以当k

Codeforces 449B Jzzhu and Cities(最短路)

题目链接:Codeforces 449B Jzzhu and Cities 题目大意:Jzzhu是一个国家的总统,这个国家有N座城市,以1为首都,已经存在了M条公路,给定M条路.并且还有K条铁轨,铁轨均有首都出发,连接si,距离为yi.现在Jzzhu想要节省经费,拆除一些铁轨,问说最多能拆除多少个铁轨,要求每座城市与首都的最短距离不变. 解题思路:最短路,多加一个标记数组,每个si标记1,如果这些点的最短距离被更新,则将对应si的标记清为0,最后统计一下剩余的标记,即为不能拆除的铁轨. #inc

Codeforces 449C Jzzhu and Apples(构造)

题目链接:Codeforces 449C Jzzhu and Apples 题目大意:Jzzhu从苹果树上获得n个苹果,标号从1~n,现在要将他们以两个为一组卖给商家,要求一组中的两个苹果的编号最大公约数大于1,分的组数尽量多. 解题思路:枚举公约数d,只枚举素数,因为合数的可以在更小的素数被枚举.将所有没用过并且编号为d的倍数的苹果拿出来,两两组队,如果个数为奇数,那么就将2d留出来.因为d>2,所以第2个肯定是2d.并且2d是2的倍数. #include <cstdio> #incl

(CF#257)C. Jzzhu and Chocolate

Jzzhu has a big rectangular chocolate bar that consists of n?×?m unit squares. He wants to cut this bar exactly k times. Each cut must meet the following requirements: each cut should be straight (horizontal or vertical); each cut should go along edg