HDU 4038 无题

来源:互联网 发布:瓦尔登湖 知乎 译本 编辑:程序博客网 时间:2024/06/06 08:57
/********************************************************************************倒不是什么太难的题,主要是细节太阴险了~具体见注释~最后学校排排名31~这几场网络赛都相当给力啊~今年挺有戏的~********************************************************************************/#include <iostream>#include <algorithm>#include <cstdlib>#include <cstring>#include <utility>#include <cstdio>#include <memory>#include <string>#include <vector>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <list>#include <map>#include <set>using namespace std;#define lowbit(x) ( (x) & ( (x) ^ (x - 1) ) )//typedef long long LL;typedef __int64 LL;typedef pair<int, int> PII;typedef pair<double, double> PDD;typedef map<int, int>::iterator MI;typedef vector<int>::iterator VI;typedef list<LL>::iterator LI;typedef set<int>::iterator SI;const int INF_INT = 0x3f3f3f3f;const LL INF_LL = 0x7fffffffffffffff;const double oo = 10e9;const double eps = 10e-7;const double PI = acos(-1.0);const int MAXN = 100004;const LL MOD = 1000000007;int test, n;LL m, arr[MAXN];inline LL llabs(LL x){return x > 0 ? x : -x;}LL pow_mod(LL a, LL k){LL r = 1;while (k){if (k & 0x1){r = (r * a) % MOD;}a = (a * a) % MOD;k >>= 1;}return r;}void ace(){int cas = 1;int ncnt, max_id, min_id;LL buf;LL max_neg, min_pos;LL two, tri, four;for (scanf("%d", &test); test--; ++cas){scanf("%d %I64d", &n, &m);ncnt = 0;max_neg = -INF_INT;for (int i = 0; i < n; ++i){scanf("%I64d", arr + i);if (arr[i] < 0){++ncnt;if (max_neg < arr[i]){max_id = i;max_neg = arr[i];}}}if (ncnt & 0x1)//如果有奇数个负数的话,尽量把最大的负数转化为正数{if (m > llabs( arr[max_id] )){m -= llabs( arr[max_id] );arr[max_id] = 0;}else{arr[max_id] += m;m = 0;}}if (m > 0)//如果有0存在的话,先尽量把0加为1{for (int i = 0; i < n && m > 0; ++i){if (0 == arr[i]){++arr[i];--m;}}}if (m > 0)//如果有1存在的话,尽量把1加为2{for (int i = 0; i < n && m > 0; ++i){if (1 == arr[i]){++arr[i];--m;}}}if (m > 0)//如果有2存在的话,尽量把2加为3{for (int i = 0; i < n && m > 0; ++i){if (2 == arr[i]){++arr[i];--m;}}}//开始变了,不能老是加最小的~不信自己列几个数试试~two = tri = four = 0;if (m > 0)//还剩下的操作尽量去添3{min_pos = INF_LL;for (int i = 0; i < n; ++i){if (arr[i] > 0 && arr[i] < min_pos)//在给定的集合中找最小的正数,显然应该>=3{min_id = i;min_pos = arr[i];}}tri = m / 3;if (1 == m % 3)//如果还剩下1个操作,那么考虑将整个集合中最小的数+1{//这个地方阴险无比啊if (tri > 0)//如果有3的话,显然把一个3->4{--tri;++four;}else//否则把集合中最小的元素+1{++arr[min_id];}}else if (2 == m % 3)//如果还剩下2个操作,那么就添一个2上去{++two;}}buf = 1;for (int i = 0; i < n; ++i){buf = (buf * arr[i]) % MOD;}buf = (buf * pow_mod(2, two)) % MOD;buf = (buf * pow_mod(3, tri)) % MOD;//tri必然很大~当然二分幂~buf = (buf * pow_mod(4, four))  % MOD;printf("Case %d: %I64d\n", cas, buf);}return ;}int main(){ace();return 0;}

原创粉丝点击