2 条题解

  • 4
    @ 2022-8-28 0:13:20

    首先微扰法证明贪心策略,目前假如到了第ii个人这里,后面的人编号是i+1i+1,设左手是lil_i,右手是rir_i,然后我们前面部分的结果都是l1l2li1l_1*l_2*……*l_{i-1},我们目前计算第i+1i+1这个人的得分,假如不交换顺序,其实就是前面的乘积在乘以lil_i然后除以ri+1r_{i+1},设前部分乘积是xx,也就是

    xliri+1\frac {x*l_i}{r_{i+1}},交换了就是xli+1ri\frac {x*l_{i+1}}{r_i}

    如果交换前的结果小就是

    xliri+1\frac {x*l_i}{r_{i+1}} < xli+1ri\frac {x*l_{i+1}}{r_i}

    通分以后约掉xx你发现就是

    liri<li+1ri+1l_i*r_i<l_{i+1}*r_{i+1}

    所以按照liril_i*r_i小的优先,排序即可。

    然后就是高精度乘法和除法的结合,这里预处理了前缀积的结果到字符串sumsum

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N = 1e3 + 5;
    int n;
    struct node
    {
    	int l, r;
    	bool operator < (const node &x) const
    	{
    		return l * r < x.l * x.r;
    	}
    } a[N];
    vector<int> s[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;
    	int x = 0;
    	for (int i = a.size() - 1; i >= 0; i--)
    	{
    		x = x * 10 + a[i];
    		c.push_back(x / b);
    		x %= b;
    	}
    	reverse(c.begin(), c.end());
    	while (c.size() > 1 && !c.back()) c.pop_back();
    //	reverse(c.begin(), c.end());
    	return c;
    }
    void print(vector<int> &c)
    {
    	for (int i = c.size() - 1; i >= 0; i--) cout << c[i];
    	cout << "\n";
    }
    vector<int> cmp(vector<int> &a, vector<int> &b)
    {
    	if (a.size() > b.size()) return a;
    	if (b.size() > a.size()) return b;
    	for (int i = a.size() - 1; i >= 0; i--)
    	{
    		if (a[i] > b[i]) return a;
    		if (a[i] < b[i]) return b;
    	}
    	return a;
    }
    int main()
    {   
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	cin >> n;
    	for (int i = 0; i <= n; i++) cin >> a[i].l >> a[i].r;
    	sort(a + 1, a + n + 1);
    	for (int i = 0; i < n; i++)
    	{
    		if (i == 0) s[i].push_back(a[0].l);
    		else
    		{
    			s[i] = mul(s[i - 1], a[i].l);
    		}
    	}
    	vector<int> ans(1, 0);
    	for (int i = 1; i <= n; i++)
    	{
    		vector<int> b = div(s[i - 1], a[i].r);
    		ans = cmp(ans, b);
    	}
    	print(ans);
        return 0; 
    }
    
    • 0
      @ 2023-3-12 16:01:41

      55555555555

      • 1

      「NOIP2012 提高组」国王游戏

      信息

      ID
      1490
      时间
      1000ms
      内存
      128MiB
      难度
      3
      标签
      递交数
      32
      已通过
      21
      上传者