首页 > 其他分享 >2024.8.19 模拟赛 24

2024.8.19 模拟赛 24

时间:2024-09-23 20:14:18浏览次数:1  
标签:24 return 2024.8 LL tr mid 19 int const

模拟赛

总是忘记保存怎么办

难得挂分。

T1 AND and SUM

签到题,如果两数按位与结果为 \(a\),那么它们的二进制重复为 \(1\) 的位一定就是 \(a\) 的二进制为 \(1\) 的位置,

所以它们相加的值至少是 \(2a\)。并且不够的差值只能在 \(a\) 二进制为零的位置补(否则会有进位),所以判 \((s-2a)\&a\) 是否为零。

赛时判了很多东西。。。

code
#include<bits/stdc++.h>
using namespace std;
#define LL __int128
int T;
LL a,s;
inline LL read()
{
	LL res=0; char x=getchar();
	while(x<'0'||x>'9') x=getchar();
	while(x>='0'&&x<='9') res=(res<<1)+(res<<3)+(x^48),x=getchar();
	return res;
}
int main()
{
	freopen("and.in","r",stdin);
	freopen("and.out","w",stdout);
	scanf("%d",&T);
	while(T--)
	{
		a=read(),s=read();
		if(a==0) printf("Yes\n");
		else if(s==0) printf("No\n");
		else if((a<<1)>s) printf("No\n");
		else if((a<<1)==s) printf("Yes\n");
		else
		{
			if((s-(a<<1))&a) printf("No\n");
			else printf("Yes\n");
		}
	}
	return 0;
}

T2 Maximum Composition

前两天刚见过的题,幸好赛时想出来了,虽然唐氏挂分。

先考虑如果确定选 \(f_1,f_2\),那么什么顺序是最优的。

  • 先选 \(f_1\):\(a_2(a_1x+b_1)+b_2=a_1a_2x+a_2b_1+b_2\)。

  • 先选 \(f_2\):\(a_1(a_2x+b_2)+b_1=a_1a_2x+a_1b_2+b_1\)

所以如果 \((a_1-1)b_2<(a_2-1)b_1\),那么先选 \(f_1\) 更优。

所以我们按上述标准排序,那么得到的就是在有序的数列上选 \(k\) 个函数使结果最大。那么可以直接 DP。

注意初始化!!!

code
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 2e5+5;
int n,k;
LL f[N][11];
struct A
{
	int a,b;
	bool operator < (const A &x) const
	{
		return 1.0*(a-1)/b<1.0*(x.a-1)/x.b;
	}
} s[N];

int main()
{
	freopen("func.in","r",stdin);
	freopen("func.out","w",stdout);
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d%d",&s[i].a,&s[i].b);
	sort(s+1,s+1+n); f[0][0]=1;//!!!!!!!!!!!!!!
	for(int i=1;i<=n;i++)
	{
		f[i][0]=1;
		for(int j=1;j<=min(k,i);j++)
		{
			f[i][j]=max(f[i-1][j-1]*s[i].a+s[i].b,f[i-1][j]);
		}
	}
	printf("%lld",f[n][k]);
	return 0;
}

T3 kangaroo

怎么想到这是预设型 DP 啊!

预设型 DP,也叫插入法 DP(这个更合适)。

我们先转化题意,将每次跳跃的点的编号组成一个序列。那么这个序列一定是波浪形的。

也就是一大一小交替放的序列的个数。考虑插入法 DP。也就是考虑填数所形成的连续段。

我们按点的编号从小到大填,这样有一个显然性质是后填的数一定比先填的大!(够显然吧)。

那么如果得到结论:填的数只能单独成段或者连接另外两个连通块

否则一定会出现一段单调的区间,这是非法的。

所以设计状态为 \(f_{i,j}\) 表示填前 \(i\) 个数形成 \(j\) 个连续段的方案数。

转移比较简单,注意特判终点和起点,它们必须在序列两端。

还有线性 \(O(n)\) 做法,如果有机会??? CEOI2016 Kangaroo 线性做法

code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e3+5,mod = 1e9+7;
int n,s,t;
int f[2][N];
int main()
{
	// freopen("kang.in","r",stdin);
	// freopen("kang.out","w",stdout);
	scanf("%d%d%d",&n,&s,&t);
	f[1][1]=1;
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=i;j++)
		{
			if(i==s||i==t) f[i&1][j]=(1ll*f[(i-1)&1][j-1]+f[(i-1)&1][j])%mod;
			else
			{
				f[i&1][j]=(1ll*f[(i-1)&1][j+1]*j+1ll*f[(i-1)&1][j-1]*(j-(i>s)-(i>t)))%mod;
			}
		}
	}
	printf("%d\n",f[n&1][1]);
	return 0;
}

T4 The Classic Problem

一眼高精度。

\(2^{1e5}\) 显然不能用常规方法做。但是 dij 求最短路是肯定的,所以我们考虑如果想实现 dij 需要维护哪些操作。

我们正常的 \(dij\) 需要维护的操作:加法比较大小

加法每次只会在二进制的某一位加一。如果加的这一位恰好为 \(1\),那么考虑进位,找出向后连续的最长的 \(1\)。如果为 \(0\),那直接加即可。

比较大小则先比较高位,不同再比较低位。

并且我们应该要能记录每一个出现的数。

上述操作都可以用主席树实现,用主席树维护 \(1e5\) 的二进制位。

由于比较的操作需要判断区间是否相等,所以考虑直接用 hash 维护,这样的话加的时候注意对齐。

单点加区间推平直接搞,查找连续的 \(1\) 线段树上二分即可,其他的正常 dij。

code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5,H = 1e9+3579,B = 233,mod = 1e9+7,V = 2e5+5;
int n,m,s,t;
int head[N],tot,p[N],p2[N],num,rt[N];
struct E {int u,v,w;} e[N<<1];
inline void add(int u,int v,int w) {e[++tot]={head[u],v,w}; head[u]=tot;}
inline void init() {p[0]=p2[0]=1; for(int i=1;i<N;i++) p[i]=1ll*p[i-1]*B%H,p2[i]=p2[i-1]*2ll%mod;}
namespace SEG
{
	struct T {int l,r,sum,hs,len;} tr[N<<7];
	inline void pushup(int k)
	{
		tr[k].len=tr[tr[k].l].len+tr[tr[k].r].len;
		tr[k].sum=tr[tr[k].l].sum+tr[tr[k].r].sum;
		tr[k].hs=(1ll*tr[tr[k].l].hs*p[tr[tr[k].r].len]%H+tr[tr[k].r].hs)%H;
	}	
	inline void bui(int &k,int l,int r,int v)
	{
		k=++num;
		if(l==r) return (tr[k].len=1,tr[k].hs=tr[k].sum=v),void(0);
		int mid=l+r>>1;
		bui(tr[k].l,l,mid,v); bui(tr[k].r,mid+1,r,v);
		pushup(k);
	}
	inline void mdf(int &k,int pre,int l,int r,int p,int v)
	{
		k=++num; tr[k]=tr[pre];
		if(l==r) return (tr[k].sum=tr[k].hs=v),void(0);
		int mid=l+r>>1;
		if(p<=mid) mdf(tr[k].l,tr[pre].l,l,mid,p,v);
		else mdf(tr[k].r,tr[pre].r,mid+1,r,p,v);
		pushup(k);
	}
	void assign(int &k,int pre,int co,int l,int r,int L,int R)
	{
		if(L<=l&&r<=R) return k=co,void(0);
		k=++num; tr[k]=tr[pre];
		int mid=l+r>>1;
		if(L<=mid) assign(tr[k].l,tr[pre].l,tr[co].l,l,mid,L,R);
		if(R>mid) assign(tr[k].r,tr[pre].r,tr[co].r,mid+1,r,L,R);
		pushup(k);
	}
	int cmp(int x,int y,int l,int r)
	{
		if(l==r) return tr[x].hs-tr[y].hs;
		int mid=l+r>>1;
		if(tr[tr[x].r].hs!=tr[tr[y].r].hs) return cmp(tr[x].r,tr[y].r,mid+1,r);
		return cmp(tr[x].l,tr[y].l,l,mid);
	}
	int afind(int k,int l,int r)
	{
		if(tr[k].sum==tr[k].len) return r;
		if(l==r) return -1;
		int mid=l+r>>1;
		int x=afind(tr[k].l,l,mid);
		if(x==mid) return max(x,afind(tr[k].r,mid+1,r));
		return x;
	}
	int find(int k,int l,int r,int p)
	{
		if(p<=l) return afind(k,l,r);
		int mid=l+r>>1;
		if(p<=mid)
		{
			int x=find(tr[k].l,l,mid,p);
			if(x==mid) return  max(x,find(tr[k].r,mid+1,r,p));
			return x;
		}
		return find(tr[k].r,mid+1,r,p);
	}
}; using namespace SEG;

inline int ad(int k,int p)
{
	int x=find(k,0,V,p),r=0,res=0; 
	if(x<0) x=p-1,r=k;
	else assign(r,k,rt[0],0,V,p,x);
	mdf(res,r,0,V,x+1,1);
	return res;
}
int d[N];
bool vs[N];
inline void dj(int s)
{
	struct node
	{
		int u,id;
		bool operator < (const node &x) const
		{
			return cmp(id,x.id,0,V)>0;
		}
	};
	priority_queue<node> q; bui(rt[0],0,V,0); bui(rt[n+1],0,V,1);
	for(int i=1;i<=n;i++) rt[i]=rt[n+1];
	rt[s]=rt[0]; q.push({s,rt[s]}); d[s]=0;
	while(!q.empty())
	{
		int u=q.top().u,id=q.top().id; q.pop();
		if(vs[u]) continue; vs[u]=1;
		for(int i=head[u];i;i=e[i].u)
		{
			int v=e[i].v;
			int now=ad(id,e[i].w);
			if(!vs[v]&&cmp(now,rt[v],0,V)<0) 
			{
				d[v]=(d[u]+p2[e[i].w])%mod; q.push({v,rt[v]=now});
			}
		}
	}
}
int main()
{
	freopen("hellagur.in","r",stdin);
	freopen("hellagur.out","w",stdout);
	scanf("%d%d",&n,&m); init(); 
	for(int i=1;i<=m;i++)
	{
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		add(x,y,z); add(y,x,z);
	}
	scanf("%d%d",&s,&t);
	dj(s);
	printf("%d\n",vs[t]?d[t]:-1);
	return 0;
}

标签:24,return,2024.8,LL,tr,mid,19,int,const
From: https://www.cnblogs.com/ppllxx-9G/p/18370387

相关文章

  • 2024.8.18 模拟赛 22
    模拟赛T1先崩,然后电脑又崩。题面都在这里了T12-Coloring原题3100,张口放T1(这是原话)看起来像dp,推了两个小时大力分讨,最后式子比我命还长。刚推出来就发现假了正解差不多人类智慧吧,也可能只是小trick。对于整张图,考虑最终染色的“形状”。(下面这个样子)图片来自题解C......
  • 【idea】log4j和slf4j配合使用问题(2024-9-23最新版本)!
    1、slf4j<!--https://mvnrepository.com/artifact/org.slf4j/slf4j-simple--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version......
  • AI 大模型计算机科学家群英传:明斯基(Marvin Lee Minsky,1927年—2016年)
    AI大模型计算机科学家群英传:明斯基(MarvinLeeMinsky,1927年—2016年)作者:禅与计算机程序设计艺术/ZenandtheArtofComputerProgramming1.背景介绍1.1问题的由来人工智能(ArtificialIntelligence,AI)作为一门横跨计算机科学、认知科学、数学等多个学科的交叉学......
  • 20240923_202514 c语言 自增自减运算符
    演练加加顺序前件优先于后件++a,先自增,再使用值a++,先使用值,后自增多个数据夹在一起测测后果演练演练......
  • [题解] ICPC网络预选赛 2024 第二场 E Escape (含题目翻译)
    [题解]ICPC网络预选赛2024第二场EEscape(含题目翻译)tag:图论、BFS、最短路题干为原文DeepL翻译题目描述Sneaker在一个巨大的迷宫中醒来,现在他想逃离这个迷宫。通过迷宫中每个房间的地图,Sneaker了解了迷宫的结构。迷宫由......
  • [GXYCTF2019]BabySQli
    这题查看源码后发现一个php文件问了ai后发现MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5是一段base32编码,经过base32解码,base64解码后的结果是select*fromuserwhereusername='$name'很明显是一个sql语句,在us......
  • 20240910_021725 c语言 强制转换
    关于强转大转小就需要强转演练......
  • 20240910_031725 c语言 字符做加法
    ......
  • 20240923 模拟赛总结
    期望得分:0+30+40+20=90实际得分:0+0+0+0=0爆了啊?!!!肚子不舒服晚了很久才开题……但开完题心就凉透了,一题不会啊!!!直接绷不住了。。T1一眼是树形DP,我、也想到了对于子树异或和为\(0,x\)去进行分析,结果感觉怎么都算不出来,看完题解才恍然大悟,原来可以从删除边数的奇偶性去进行DP......
  • 信息学奥赛复赛复习01-CSP-J2019-01-字符、字符数组、字符串、string、字符串读取
    信息学奥赛复赛复习01-CSP-J2019-01-字符、字符数组、字符串、string、字符串读取PDF文档公众号回复关键字:2024092312019CSP-J题目1数字游戏[题目描述]小K同学向小P同学发送了一个长度为8的01字符串来玩数字游戏,小P同学想要知道字符串中究竟有多少个1。注......