贪心地推出一个结论就好,证明很easy (直接将所有大臣按左右手上的数的乘积从小到大排序,得到的序列就是最优排队方案)
代码:
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
const int N = 1010;
int n;
PII p[N];
vector<int> mul(vector<int>a, int b)
{
vector<int> c;
int t = 0;
for (int i = 0; i < a.size(); i ++ )
{
t += a[i] * b;
c.push_back(t % 10);
t /= 10;
}
while (t)
{
c.push_back(t % 10);
t /= 10;
}
return c;
}
vector<int> div(vector<int>a, int b)
{
vector<int> c;
//标记,不放前导0
bool is_first = true;
for (int i = a.size() - 1, t = 0; i >= 0; i -- )
{
t = t * 10 + a[i];
int x = t / b;
if (!is_first || x)
{
is_first = false;
c.push_back(x);
}
t %= b;
}
reverse(c.begin(), c.end());
return c;
}
vector<int> max_vec(vector<int> a, vector<int> b)
{
if (a.size() > b.size()) return a;
if (a.size() < b.size()) return b;
//vector存的是小位在前,高位在后,所以要倒过来判断
if (vector<int>(a.rbegin(), a.rend()) > vector<int>(b.rbegin(), b.rend())) return a;
return b;
}
int main()
{
cin >> n;
for (int i = 0; i <= n; i ++ )
{
int a, b;
cin >> a >> b;
p[i] = {a * b, a};
}
sort(p + 1, p + n + 1);
vector<int> product(1, 1);
vector<int> res(1, 0);
for (int i = 0; i <= n; i ++ )
{
if (i) res = max_vec(res, div(product, p[i].first / p[i].second));
product = mul(product, p[i].second);
}
for (int i = res.size() - 1; i >= 0; i -- ) cout << res[i];
cout << endl;
return 0;
}
机器人:
思路:
代码1(贪心+__int128):
注意: __int128要一位一位的读入 , 一位一位的输出
#include <bits/stdc++.h>
#define lll __int128
using namespace std;
struct T{
int x,y;
}c[22];
bool cmp(T &a,T &b){return a.x*b.y+a.y<b.x*a.y+b.y;}
void print(lll x){
if(x>9) print(x/10);
putchar(x%10+'0');
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0);
int n,x;
cin>>n>>x;
lll res=x;
for(int i=0;i<n;++i) cin>>c[i].x>>c[i].y;
sort(c,c+n,cmp);
for(int i=0;i<n;++i) res = res*c[i].x+c[i].y;
print(res);
return 0;
}
代码2(贪心+大数板子):
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#include <set>
#include <map>
#include <sstream>
#define pb push_back
#define debug(x) cout<<#x<<":"<<x<<endl;
#define f(i,a,n) for(int i=a;i<n;++i)
#define ff(i,a,n) for(int i=a;i<=n;++i)
using namespace std;
typedef long long ll;
typedef double dbl;
typedef pair<int, int> pi;
const int INF = 0x3f3f3f3f;
inline ll in() { char ch = getchar();ll x = 0, f = 1;while (ch<'0' || ch>'9') { if (ch == '-')f = -1;ch = getchar(); }while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0';ch = getchar(); }return x * f; }
inline int lowbit(int x) { return x&(-x);}
ll qpow(ll a, ll n, ll m) { ll s = 1;while (n) { if (n & 1) { s = s * a % m; }a = (a*a) % m;n = n / 2; }return s; }
void ex_gcd(ll a, ll b, ll &x, ll &y, ll &d) { if (!b) { d = a, x = 1, y = 0; } else { ex_gcd(b, a % b, y, x, d);y -= x * (a / b); } }
ll inv(ll t, ll p) { ll d, x, y;ex_gcd(t, p, x, y, d);return d == 1 ? (x % p + p) % p : -1; }
bool isPrime(ll x) { if (x == 2)return true;if (x % 2 == 0)return false;for (ll i = 2;i*i <= x;i++) if (x % i == 0)return false; return true; }
inline ll inv2(ll x,ll p) { return qpow(x,p-2,p);}
ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
ll lcm(ll a, ll b) { return 1LL*a/gcd(a,b)*b;}
int dx[4]={0,0,-1,1},dy[4]={1,-1,0,0};
struct f{
ll a,b;
}c[22];
bool cmp(f t1,f t2){
return t2.a*t1.b-t1.a*t2.b > t1.b-t2.b;
}
vector<int> add(vector<int> &A, vector<int> &B){
if (A.size() < B.size()) return add(B, A);
vector<int> C;
int t = 0;
for (int i = 0; i < A.size(); i ++ ){
t += A[i];
if (i < B.size()) t += B[i];
C.push_back(t % 10);
t /= 10;
}
if (t) C.push_back(t);
return C;
}
vector <int> mul(vector <int> & A, int b) {
vector <int> C;
int t = 0;
for (int i = 0; i < A.size(); i ++) {
t += A[i] * b; // t + A[i] * b = 7218
C.push_back(t % 10); // 只取个位 8
t /= 10; // 721 看作 进位
}
while (t) {// 处理最后剩余的 t
C.push_back(t % 10);
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();//12345*0 != 00000
return C;
}
void solve(){
ll n,x;
cin>>n>>x;
f(i,0,n)c[i].a=in(),c[i].b=in();
sort(c,c+n,cmp);
vector<int>res;
while(x){res.pb(x%10);x/=10;}
f(i,0,n){
res=mul(res,c[i].a);
vector<int>tem;
while(c[i].b){
tem.pb(c[i].b%10);c[i].b/=10;
}
res=add(res,tem);
}
for(int i=res.size()-1;i>=0;i--)
cout<<res[i];
}
int main(){
int T=1;
while(T--) {
solve();
}
return 0;
}
代码3(状压+记忆化dp):
思路:
f
[
s
t
]
f[st]
f[st]表示已经经过了
s
t
st
st状态的机器人时,最大的得分是多少
f
[
s
t
]
=
m
a
x
(
f
[
s
t
0
]
∗
a
j
+
b
j
)
f[st]=max(f[st_{0}]*a_{j}+b_{j})
f[st]=max(f[st0]∗aj+bj)
s
t
0
st_{0}
st0中第
j
j
j为为
0
0
0,即第
j
j
j个机器人还没有用
s
t
st
st中第
j
j
j位为
1
1
1,其他位与
s
t
0
st_{0}
st0相同
#include <bits/stdc++.h>
using namespace std;
int n, x;
int a[30], b[30];
__int128 f[(1<<20)+100];
__int128 dp(int st)
{
if (f[st] != 0) return f[st];
for (int i = 0; i < n; i++)
{
//如果st里面包含第i个机器人
if ((st & (1 << i)) != 0)
{
//单独把第i位从1变为0,其他位不变
int t = st ^ (1 << i);
f[st] = max(f[st], dp(t)*a[i+1] + b[i+1]);
}
}
return f[st];
}
inline void print(__int128 x)
{
if(x<0){putchar('-');x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
int main()
{
scanf("%d%d", &n, &x);
for (int i = 1; i <= n; i++)
scanf("%d%d", &a[i], &b[i]);
f[0] = x;
print(dp((1<<n)-1));
return 0;
}
代码4(状压+dp):
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pb push_back
#define fir first
#define sec second
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, l, r) for (int i = l; i >= r; i--)
#define mset(s, t) memset(s, t, sizeof(s))
#define mcpy(s, t) memcpy(s, t, sizeof(t))
//ckmax:把两者的较大值赋给前面
template<typename T1, typename T2> void ckmax(T1 &a, T2 b) { if (a < b) a = b; }
int read() {
int x = 0, f = 0; char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) x = 10 * x + ch - '0', ch = getchar();
return f ? -x : x;
}
template<typename T> void print(T x) {
if (x < 0) putchar('-'), x = -x;
if (x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
template<typename T> void print(T x, char let) {
print(x), putchar(let);
}
//lowbit:二进制最低位的1与后边的0组成的数
int lowbit(int t){
return t&(-t);
}
const int N = 20;
__int128 dp[1 << N];
int a[N], b[N], bit[1 << N], n, x;
int main() {
cin >> n >> x;
for (int i = 0; i < n; i++) cin >> a[i] >> b[i];
for (int i = 0; i < n; i++) bit[1 << i] = i;
dp[0] = x;
int all = (1 << n) - 1;
for (int st = 0; st <= all; st++) {
int t = all ^ st;//st里面1变0,0变1
while (t) {
int y = bit[lowbit(t)];
t ^= 1 << y;
ckmax(dp[st | 1 << y], dp[st] * a[y] + b[y]);
}
}
print(dp[all]);
return 0;
}