題目描述
小Q是籃球訓練隊的教練,籃球隊新加入了N名隊員,第i名隊員的籃球水平值爲ai。
小Q現在要把他們按照以下的要求分爲A隊和B隊進行訓練:
1、A隊的隊員水平值之和嚴格大於B隊的隊員水平值之和
2、對於A隊中的任意一名隊員,如果把他分配到B隊,A隊的水平值之和就會嚴格小於B隊的水平值之和。
3、每個隊員必須要加入一個隊伍
小Q現在想知道有多少種方案可以按照以上要求完成分隊。
題目鏈接
輸入描述:
輸入包括兩行, 輸入的第一行爲一個正整數n(2 <= N <= 50), 表示隊員的數量。
第二行包括N個正整數 ai(1 <= ai <= 6 × 104), 表示每名隊員的籃球水平值, 以空格分割。
輸出描述:
輸出一個正整數, 表示方案數。
示例1
輸入
4
5 4 7 6
輸出
2
AC代碼:
常數優化版本
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 0x3f3f3f3f;
int dp[600000 * 50 + 1] = {0};
int gcd(int a, int b)
{
/*if (a > b)
swap(a, b);*/
return b ? gcd(b, a % b) : a;
}
ll solve(int *arr, int n)
{
sort(arr, arr + n, greater<int>());
int GCD_Number = arr[0];
for (int i = 1; i < n; i++)
GCD_Number = gcd(GCD_Number, arr[i]);
ll tot = 0;
//cout << "GCD_Number = " << GCD_Number << endl;
for (int i = 0; i < n; i++)
{
arr[i] /= GCD_Number; //常數優化,tot指數減小
tot += arr[i];
}
ll ans = 0;
dp[0] = 1;
//for (int i = 1; i < maxn; i++)
// dp[i] = 0;
for (int i = 0; i < n; i++)
{
for (ll j = tot; j >= arr[i]; j--)
{
dp[j] += dp[j - arr[i]];
if (j > tot - j && j - arr[i] < tot - j + arr[i])
ans += dp[j - arr[i]];
}
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
int n;
while (cin >> n)
{
int* arr = new int[n];
//ll tot = 0;
int tmp = 1;
for (int i = 0; i < n; i++)
{
cin >> arr[i];
//tot += arr[i];
}
ll ans = 0;
ans = solve(arr, n);
cout << ans << endl;
}
return 0;
}
無常數優化版本
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 0x3f3f3f3f;
int dp[600000 * 50 + 1] = {0};
/*int gcd(int a, int b)
{
if (a > b)
swap(a, b);
return b ? gcd(b, b % a) : a;
}*/
ll solve(int *arr, int n, ll tot)
{
sort(arr, arr + n, greater<int>());
/*int GCD_Number = arr[0];
for (int i = 1; i < n; i++)
GCD_Number = gcd(GCD_Number, arr[i]);
for (int i = 0; i < n; i++)
{
arr[i] /= GCD_Number;
tot -= arr[i];
}*/
ll ans = 0;
dp[0] = 1;
//for (int i = 1; i < maxn; i++)
// dp[i] = 0;
for (int i = 0; i < n; i++)
{
for (ll j = tot; j >= arr[i]; j--)
{
dp[j] += dp[j - arr[i]];
if (j > tot - j && j - arr[i] < tot - j + arr[i])
ans += dp[j - arr[i]];
}
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
int n;
while (cin >> n)
{
int* arr = new int[n];
ll tot = 0;
int tmp = 1;
for (int i = 0; i < n; i++)
{
cin >> arr[i];
tot += arr[i];
}
ll ans = 0;
ans = solve(arr, n, tot);
cout << ans << endl;
}
return 0;
}
時空消耗對比:
常數優化後,
時間減少:
104 ms
佔比減少:
× 100% 34.6 %
空間減少:
5260 KB
佔比減少:
× 100% 44.2%