首页 > 其他分享 >P10786 [NOI2024] 百万富翁

P10786 [NOI2024] 百万富翁

时间:2024-08-28 22:36:38浏览次数:5  
标签:10 cnt frac P10786 int 百万富翁 NOI2024 operatorname define

思路:

先考虑 Sub1 的部分分,暴力算法:

暴力询问所有 \(i<j\) 的数对 \((i,j)\)。
则一个 \(i\) 为最大值当且仅当 \((i,j)\) 的返回值都是 \(i\) 且在 \(i\) 之前没有满足此条件的位置。

则设 \(\operatorname{F}(n) = \frac{n(n-1)}{2}\) 表示暴力找出 \(n\) 个数中的最大值需要的询问次数,注意到 \(\operatorname{F}(1000) = 499500\),故可以通过 Sub1。

对于 Sub2,直接暴力肯定是不行的,但是注意到 \(t\) 的值开大了,故我们没必要一步到位,可以逐步缩小范围。

定义 \(\operatorname{W}(a,b)\) 表示原先最大值候选有 \(a\) 个,经过一次请求筛到 \(b\) 个候选人的最小询问次数;考虑分为 \(b\) 组,每组有 \(\lfloor \frac{a}{b} \rfloor \sim \lceil \frac{a}{b} \rceil\) 人,故:

\[\operatorname{W}(a,b) = (b - b\bmod a) \operatorname{F}(\lfloor \frac{a}{b} \rfloor) + (b \bmod a) \operatorname{F}(\lceil \frac{a}{b} \rceil) \]

现在我们的目的就是找到一个合理的筛检最大值候选的序列 \(h\),使得长度 \(len \le t\) 且 \(\sum\limits_{i=1}^{len-1} \operatorname{W}(h_i,h_{i+1}) \le s\)。

爆搜经过实测可以搜到 \(t=9\) 的情况,在 \(t=8\) 时几乎无法跑出来。

考虑动态规划算法,令 \(dp_{i,j}\) 表示 \(W_i = j\) 的情况下的最小询问数,则状态转移方程为:

\[dp_{i,j} = \min_{k=j+1}^n dp_{i-1,k} + \operatorname{W}(k,j) \]

时间复杂度为 \(O(tn^2)\),大概有 \(10^{13}\),按照最低预算,计算机 1s 可以跑 \(10^8\),则 \(\frac{10^{13}}{10^{8}} = 10^5\),则 \(\frac{10^5}{64^2} \approx 24\),大概要跑 \(1\) 天的时间,是肯定不行的。

可以有一个猜想,每次候选人的数量至少要减半,这样一定不会太劣,这样我们就将范围个缩小了,对于 \(dp_{i,j}\) 有效的 \(j\) 只有 \(\frac{n}{2^{i-1}}\),枚举的 \(k\) 大概是 \((j,2j]\),这样大概可以缩到 \(10^{11}\) 左右,可以在 1h 内跑完。

最后根据我们得到的 \(h\) 模拟一下分组求最大值的过程即可。

单组数据时间复杂度最多为 \(O(Nt)\)。

完整代码:

#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
#define For(i,l,r) for(int i=l;i<=r;i++)
#define _For(i,l,r) for(int i=r;i>=l;i--)
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
const int maxn=1e6+10;
std::vector<int> ask(std::vector<int> a, std::vector<int> b);
int n;
vector<int> a,b,h;
namespace Sub1{
    int cnt=0;
    int work(){
    	a.clear(),b.clear();
    	cnt=0;
        vector<int> l(n,0),r(n,0);
        For(i,0,n-1){
            l[i]=cnt;
            For(j,i+1,n-1){
                a.push_back(i);
                b.push_back(j);
                ++cnt;
            }
            r[i]=cnt-1;
        }
        h=ask(a,b);
        For(i,0,n-1){
            bool F=1;
            For(j,l[i],r[i]){
                if(h[j]!=i){
                    F=0;
                    break;
                }
            }
            if(F)
              return i;
        }
        return 0;
    }
};
namespace Sub2{
	int cnt=0;
	int s[maxn];
	vector<int> E[maxn];
	stack<int> S;
	int p[]={1000000,500000,250000,125000,62498,20832,3472,183,1};
	void solve(int x){
		s[x]=a.size();
		int n=E[x].size();
        For(i,0,n-1){
            For(j,i+1,n-1){
                a.push_back(E[x][i]);
                b.push_back(E[x][j]);
            }
        }
	}
	int get(int x){
		int g=s[x],n=E[x].size();
		For(i,0,n-1){
			bool F=1;
			For(j,i+1,n-1)
			  if(h[g++]!=E[x][i])
				F=0;
			if(F)
			  return E[x][i];
		}
		return 0;
	}
	void get(int X,int Y){
		cnt=0;
		int l=0,cnt=0,g=0,B=X/Y;
		For(i,1,Y)
		  E[i].clear();
		while(!S.empty()){
			++l;
			int x=S.top();
			S.pop();
			if((l-1)/B+1!=cnt)
			  ++cnt;
			if(cnt<=Y)
			  E[cnt].push_back(x);
			else{
				++g;
				E[g].push_back(x);
			}
		}
		For(i,1,Y)
		  solve(i);
		h=ask(a,b);
		For(i,1,Y){
			int x=get(i);
			S.push(x);
		}
	}
	int work(){
		while(!S.empty())
		  S.pop();
    	_For(i,0,n-1)
    	  S.push(i);
		For(i,1,8){
			a.clear(),b.clear();
			get(p[i-1],p[i]);
		}
		return S.top();
	}
};
int richest(int N,int T,int S){
    n=N;
    if(n<=1000)
      return Sub1::work();
    else
      return Sub2::work();
}

标签:10,cnt,frac,P10786,int,百万富翁,NOI2024,operatorname,define
From: https://www.cnblogs.com/rgw2010/p/18385632

相关文章

  • P10789 [NOI2024] 登山
    思路:我们可以对于每个\(i\)找到它能跳到的最远的点和最近的点,倍增求一下\(k\)级祖先即可,令\([l_i,r_i]\)新表示\(i\)能跳到其祖先中深度在\([l_i,r_i]\)内的点;同时令\(lim_i=d_i-h_i-1\)表示\(i\)至少要跳到\(lim_i\)的深度。考虑动态规划算法,令\(dp_i\)......
  • P10785 [NOI2024] 集合
    思路:容易发现,区间\([l,r]\)中\(A\)与\(B\)等价的充分必要条为:两个序列中所有元素对于在区间\([l,r]\)内的出现集合组成的集合相等。这样才可以使得存在一种对应的映射方案使得等价。考虑哈希判定。设\(S_i\)表示\(i\)出现的位置的集合,则设\(\operatorname......
  • NOI2024 D1T3 口胡题解
    NOI2024D1T3口胡题解题目条件其实就是说对于点对\((a,b)\),从\(a\)到\(b\)的路径上至少要有一条从\(b\)指向\(a\)​的边。将初始状态记作\((T,S)\)​,其中\(T\)​是树,\(S\)​是二元组\((a,b)\)​的集合。注意到特殊性质A蕴含了:如果对于所有二元组\((a,b)\),\(a......
  • 成为百万富翁的几率 vs. 被公交车撞的几率:一次 ES|QL 分析
    作者:来自Elastic BahaAzarmiES|QL专为快速、高效地查询大型数据集而设计。它具有简单的语法,可让你使用基于管道的语言轻松编写复杂查询,从而降低学习曲线。我们将使用ES|QL运行统计分析并比较不同的几率。如果你在读这篇文章,你可能想知道在达到与被公交车撞同样几率之......
  • NOI2024 游记
    Day0报到。这是第一次参加NOI,有点紧张。CQ真的好热啊qaq教练飞机晚点,但是我的学籍证明在教练那。由于害怕教练来得太迟错过报名时间,就先去报到了,但是被告知没有学籍证明不能拿胸牌,没有胸牌不能进宿舍,于是坐在宿舍楼下等了\(\infty\)分钟。期间在宿舍到大门的坡道上来回......
  • NOI2024 F 类游记
    前情提要:省选\(\rmDay1T1\)\(\rmCE\),获得\(\rmF\)类资格。前面一周天天有多校或者模拟赛,抽不出完整的\(5h\)供我\(\rmvp\),于是把\(\rmDay1\)的\(\rmvp\)放到了周日。假装我笔试\(\rmAK\)了。但是已经过去这么多天了,不可避免的知道了一些东西,包括队线,某些题......
  • NOI2024 摆烂记
    某菜鸡初三Oier的NOID类游记。。。。Day-8~Day-2因为重庆育才有冲刺NOI的训练(其实就是多校联考),所以我提前几天来到了重庆。然后就是正常的多校集训。最后一天休息时还去爬了山,不得不说重庆是真的热,爬完真的累死我了。Day-1下午是报道,然后就逛了一下CQYC。食堂还是自助,而......
  • NOI2024 赛前训练记录(2)
    5.1P9662首先可以设\(dp_{i,j}\)表示考虑了前\(i\)个数,当前在开头位置的是原来排第\(j\)的数的答案。转移如果\(j\)仍然合法,那么只需要转移到\(dp_{i+1,j}\)。否则要转移到\(i+1\)这个数在\(1\)或者\(m\)位置的情况。时间复杂度\(O(n^2)\)。考虑优化这个东西,发......
  • NOI2024 游记 | 如果这只是梦
    NOI2024游记|如果这只是梦省流:HBA类打铜,内含很多个人想法,可能更像对这一赛季想说的鲜花我终于站在了国赛场上,这也是第一次站在赛场上。第一天考试的时候我无法抑制紧张的心情,看到T2居然是真的交互题当时顿时心凉了半截,我开场前1h心跳一直很快,后面都有些喘不过气来,花了......
  • NOI2024 题解
    D2T3树形图首先判掉一些case将任意一个\(1\)类点定为根,求出一棵dfs树,则图上的非树边只有返祖边,没有横叉边。\(1\)类点考虑在这棵dfs树的基础上求出所有\(1\)类点:考虑\(fa_u\tou\)这条边被几条返祖边覆盖了,由于这是一个强连通分量,所以子树中至少有一条返祖边覆......