首页 > 其他分享 >8.8模拟赛小结

8.8模拟赛小结

时间:2023-08-12 23:13:09浏览次数:39  
标签:int 8.8 ll long mod 小结 线段 模拟 define

0.前言

又是爆炸的一场

T1 只因数分解

出题人树脂666 是不是香菜逢仁鸡
T1
成分过于复杂

题意:输入一个数\(n\) 分解一个\(m\)

定义只因数为 \(x\) 为 \(n!\) 的因数

构造一种方案 使得质因数小于等于\(n\)

思考:要知道的是\(m\leq n!\)

所以我们不妨考虑\(m\)拆成几个数 倒过来思考 就是阶乘进制

每一位都是\(n*(n-1)*(n-2)…(n-k)*a_k\)

因为\(a_k \leq n\) 所以这肯定是一个正确拆分

然后暴拆即可

Code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int g,sum[25],l;
ll n,m,ans,t;
ll q[25];
int main()
{
	scanf("%d",&g);
	while(g--)
	{
		scanf("%lld%lld",&n,&m);
		l=0;
		while(m)
		{
			ll t=1;
			for(ll i=n;i>=1;i--)
				if(t*i<=m) t*=i;
			q[++l]=t;
			m-=t;
		}
		printf("%d\n",l);
		for(int i=1;i<=l;i++)
			printf("%lld ",q[i]);
		printf("\n");
	}
	return 0;
}

T2 宇宙射线 原题

T2
老逼灯题目

Subtask1

太简单了 直接\(O(n!)\)枚举集合\(O(nm)\)判断即可 时间复杂度\(O(nm*n!)\)

Subtask2

看见\(n\)十分的小 因为当前面的数取定了 后面的数取到的数就是固定的

考虑 装压DP

定义 \(f[i]\) 表示\(i\)拆分二进制后对应位上都有的最优解 每次更新情况 \(O(n)\)转移

时间复杂度\(O(2^nn)\)

Code

#include<bits/stdc++.h>
#define N 605
#define ll long long
using namespace std;
ll mod=998244353;
ll pow2[N],f[(1<<20)+5],vis[(1<<20)+5];
int n,m,a[N],op[N][N]; 
int main()
{
	scanf("%d%d",&n,&m);
	pow2[0]=1;
	for(int i=1;i<=n;i++)
		pow2[i]=pow2[i-1]*2;
	for(int i=1;i<=m;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=m;i++)
	{
		op[a[i]+i-1][0]=1;
		for(int j=1;j<=n;j++)
			scanf("%d",&op[a[i]+i-1][j]);
	}
	vis[0]=1;
	for(int i=0;i<(1<<n);i++)
	{
		if(!vis[i]) continue;
		int s=0,t=i;
		for(int j=1;j<=n;j++)
			if(i&(1<<j-1)) s++;
		if(op[s][0])
		{
			for(int j=1;j<=n;j++)
				if(!(i&(1<<op[s][j]-1)))
				{
					t|=(1<<op[s][j]-1);
					break;
				}
		}
		for(int j=1;j<=n;j++)
			if(!(t&(1<<j-1)))
			{
				f[t|(1<<j-1)]=max(f[t|(1<<j-1)],f[i]+pow2[n-j]);
				vis[t|(1<<j-1)]=1;
			}
	}
	cout<<f[(1<<n)-1]%mod;
	return 0;
}

50pts到手

Subtask3

考虑贪心。

因为 \(2^n>2^{n-1}+2^{n-2}+2^{n-3}+…2^0\)

因此 能拿前面的必须拿前面的

考虑枚举每个状态能不能拿 把能拿的所有东西丢进集合\(S\)里面

我们可以发现 每次拿可以检查一次:

  • 从左扫一遍\(1\to m\)射线
  • 如果当前实验不输入\(S\) 而且没有做过 那么可以直接让宇宙射线轰了这个实验
  • 否则如果当前这个实验属于\(S\) 而且没有做过 那么必须做掉这个实验 不做就被射线轰了 所以记录一下有几个必做实验
  • 判断必做实验的个数是不是大于\(a_i\) 如果当前条件是\(a_i\)个数之前 大于\(a_i\) 那么就是不行 不能把这个实验丢进集合里面

时间复杂度\(O(n^2m)\)

能通过此题

Code

#include<bits/stdc++.h>
#define N 605
#define ll long long
using namespace std;
ll mod=998244353;
ll pow2[N],ans;
int n,m,a[N],b[N][N]; 
int used[N],vis[N];
bool check(int x)
{
	fill(used+1,used+1+n,0);
	int sum=0;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(!vis[b[i][j]]&&!used[b[i][j]])
			{
				used[b[i][j]]=1;
				break;
			}
			if(!used[b[i][j]])
			{
				used[b[i][j]]=1;
				sum++;
			}
		}
		if(sum>a[i]) return 0;
	}
	return 1;
}
int main()
{
	scanf("%d%d",&n,&m);
	pow2[0]=1;
	for(int i=1;i<=n;i++)
		pow2[i]=pow2[i-1]*2%mod;
	for(int i=1;i<=m;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=m;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&b[i][j]);
	for(int i=1;i<=n;i++)
	{
		vis[i]=1;
		if(check(i))
			ans=(ans+pow2[n-i])%mod;
		else vis[i]=0;
	}
	cout<<ans;
	return 0;
}

T3崩原之战Ⅱ

T3
____怎么你了

出题人给出化简题意:

本质不同的方案应该是选择一些要求集合,满足存在一种人才分配方案满足这些要求。

即你可以满足这个要求,但是不选择这个要求。

Subtask2

注意到 所有策划的要求无交集 那么肯定每个策划漫不满足都可以

直接输出\(2^n\)即可

期望得分20pts

Subtask1

注意到\(n\)很小 直接暴力 dfs枚举即可

期望得分20pts

错解

考虑 dp

首先把序列按照右端点排序 定义\(f_i\)考虑前\(i\)条线段 当前线段必选有多少种方案

\[f_i=1+\sum\limits_{j=1,c_i=c_j}^{i-1}f(j)+\sum\limits_{j=1,c_i\ne c_j,rj<li}^{i-1}f(j) \]

因为前面的同颜色的可以随便选 不同颜色的与我没有交集也能是子问题

但是这样是错的 因为如果当时考虑了\(x\)线段 左端点是\(l_x\)

后面考虑了\(y\)线段 左端点是\(l_y\)

如果\(l_y < l_x\) 以前在\(x\)会考虑\(y\)的一段区间随便选 这是不合法的

比如 \([3,4],[6,7],[1,8]\) 颜色为\(0,1,1\)

容易得到\(f_2=2\) 因为\([3,4]\)可选可不选

但是\(f_3\)=2 因为\([6,7]\)可选可不选 但是\([3,4]\)不能选

如果直接从\(f_2\)转移 那么状态在\(f_2\)时是没有考虑\(1\to 5\)这一段的

所以转移会出错 得到\(f_3=f_2+1=3\)

时间复杂度 \(O(n^2)\)

半正解

根据错解我们得知 不能只考虑一条线段 考虑一组线段

考虑一组线段 转移时必须是和当前颜色不同颜色的线段转移过来

这样子可得

\[f_i=\sum\limits_{j=0,c_i\ne c_j,r_j<i_l}^{i}f_j*2^{ask(i-1,a[j].r,c)} \]

其中\(ask(i,r,c)\)表示前\(i\)中有多少条线段左端点大于\(r\)且颜色为\(c\)

可以理解为 求\(r_j\to i_l\)中完全包含在内的线段

为什么呢?因为我们考虑的是不同颜色线段转移 我们考虑的是\(j\)线段为终点的颜色段 所以\(j\)后面的颜色都是一段 那么同一段有多少种这样的线段我们可以算出来 这些线段都有选和不选两种情况(注意:这里和原题意不符 看修改题意) 因此为\(2^x\)

初始化:我们定义\(r_0=0\),\(f_0=1\) 表示从0为结尾,以第\(1\)条线段为起始的相同颜色段

统计答案:明显有一种情况 全都不满足(一个人都不去) 考虑每段颜色结尾 答案为\(ans=1+\sum\limits_{i=1}^nf_i\)

优化:判断两个颜色是否相同比较麻烦 \(dp\)可以再开一维颜色维 可以不写判断\(c_i\ne c_j\)去掉一个\(if\)语句

时间复杂度\(O(n^3)\)

期望得分 20pts

最朴素DP:

#include<bits/stdc++.h>
#define N 1000005
#define ll long long
using namespace std;
ll mod=998244353,pw[N],ans;
int T;
int n;
ll f[N][2],g[N][2];
struct node{
	int l,r,x;
}a[N];
bool cmp(node a,node b)
{
	return a.r<b.r;
}
int ask(int x,int r,int c)
{
	int sum=0;
	for(int i=1;i<=x;i++)
	if(c==a[i].x&&a[i].l>=r) sum++;
	return sum;
}
int main()
{
	pw[0]=1;
	for(int i=1;i<=N-4;i++) pw[i]=pw[i-1]*2%mod;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].x);
		sort(a+1,a+1+n,cmp);
		ans=0;
		f[0][0]=f[0][1]=1;
		for(int i=1;i<=n;i++)
		{
			f[i][0]=f[i][1]=0;
			int c=a[i].x;
			for(int j=0;j<i;j++)
			{
				if(a[j].r>=a[i].l) break;
				f[i][c]+=f[j][c^1]*pw[ask(i-1,a[j].r+1,c)]%mod;f[i][c]%=mod;
			}
			ans+=f[i][a[i].x];ans%=mod;
		}
		ans++,ans%=mod;
		printf("%lld\n",ans);
	}
	return 0;
}

一部分的优化

\(O(n^3)\)20pts

稳定发挥 甚至不如直接输出\(2^n\)

我们发现每次\(ask\)是肯定可以优化的 每次做一遍太慢了

观察到每次\(ask\)只是往前推一个\(i\) 里面\(r_j\)的参数不变 因此我们可以开一个\(g_{j,c}\)存下\(ask\)的值 每次修改完改一下\(g\)值即可

因为已经按\(r\)排序了 因此\(r\)是单调递增的 可以用一个二分去掉\(rj<al\)的这句话 直接找到循环终止点

时间复杂度\(O(n^2)\)

#include<bits/stdc++.h>
#define N 1000005
#define ll long long
using namespace std;
ll mod=998244353,pw[N],ans;
int T;
int n,r[N];
ll f[N][2],g[N][2];
struct node{
	int l,r,x;
}a[N];
bool cmp(node a,node b)
{
	return a.r<b.r;
}
int main()
{
	pw[0]=1;
	for(int i=1;i<=N-4;i++) pw[i]=pw[i-1]*2%mod;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].x);
		sort(a+1,a+1+n,cmp);
		ans=0;
		for(int i=1;i<=n;i++)
			r[i]=a[i].r;
		fill(&g[0][0],&g[n+5][0],0);
		f[0][0]=f[0][1]=1;
		for(int i=1;i<=n;i++)
		{
			f[i][0]=f[i][1]=0;
			int c=a[i].x,end=lower_bound(r+1,r+1+i,a[i].l)-r;
			for(int j=0;j<end;j++)
				f[i][c]+=f[j][c^1]*pw[g[j][c]]%mod,f[i][c]%=mod;
			for(int j=0;j<end;j++)
				g[j][c]++;
			ans+=f[i][c];ans%=mod;
		}
		ans++,ans%=mod;
		printf("%lld\n",ans);
	}
	return 0;
}

正解

\(O(n^2)\) emmmm 只能过Subtask1 优化了和没优化一个分

现在要继续改

我们发现 \(pw[g[j][c]]\) 其实可以变成 \(g[j][c]\) 不要让\(g\)数组当成\(2\)的指数 每次修改直接乘\(2\)即可

为了区分 将\(g\)数组变成\(h\)数组

for(int j=0;j<end;j++)
	f[i][c]+=f[j][c^1]*h[j][c]%mod,f[i][c]%=mod;
for(int j=0;j<end;j++)
	h[j][c]=h[j][c]*2%mod;

发现 \(f[j][1-c]\) 也是一个定值

可以直接初始化就给它丢进去

for(int j=0;j<end;j++)
	f[i][c]+=h[j][c]%mod,f[i][c]%=mod;
for(int j=0;j<end;j++)
	h[j][c]=h[j][c]*2%mod;
h[i][c^1]=f[i][c];
h[i][c]=0;

其实修改到这里已经差不多了

四条语句分别要做的是:

  • 区间查询
  • 区间乘2
  • 单点修改

直接丢上两棵线段数维护即可

时间复杂度 \(O(n\log n)\)

期望得分100pts

#include<bits/stdc++.h>
#define N 1000005
#define ll long long
using namespace std;
ll mod=998244353,ans;
int T;
int n,r[N];
struct node{
	int l,r,x;
}a[N];
struct tree{
	ll tr[N*4],lz[N*4];
	void clear(int n)
	{
		for(int i=1;i<=n*4;i++)
			tr[i]=0,lz[i]=1;
	}
	void Pushup(int x)
	{
		tr[x]=(tr[x*2]+tr[x*2+1])%mod;
	}
	void Pushdown(int x)
	{
		if(lz[x]==1) return;
		tr[x*2]*=lz[x];tr[x*2]%=mod;
		lz[x*2]*=lz[x];lz[x*2]%=mod;
		
		tr[x*2+1]*=lz[x];tr[x*2+1]%=mod;
		lz[x*2+1]*=lz[x];lz[x*2+1]%=mod;
		
		lz[x]=1;
	}
	void modify(int l,int r,int L,int x,ll v)
	{
		if(l>L||r<L) return ;
		if(l==r)
		{
			tr[x]=v;
			return;
		}
		Pushdown(x);
		int mid=(l+r)/2;
		modify(l,mid,L,x*2,v);
		modify(mid+1,r,L,x*2+1,v);
		Pushup(x);
		return;
	}
	void updata(int l,int r,int L,int R,int x)
	{
		if(l>R||r<L) return;
		if(l>=L&&r<=R)
		{
			tr[x]=tr[x]*2%mod;
			lz[x]=lz[x]*2%mod;
			return;
		}
		Pushdown(x);
		int mid=(l+r)/2;
		updata(l,mid,L,R,x*2);
		updata(mid+1,r,L,R,x*2+1);
		Pushup(x);
	}
	ll query(int l,int r,int L,int R,int x)
	{
		if(l>R||r<L) return 0;
		if(l>=L&&r<=R) return tr[x];
		Pushdown(x);
		int mid=(l+r)/2;
		return (query(l,mid,L,R,x*2)+query(mid+1,r,L,R,x*2+1))%mod;
	}
}tr[2];
bool cmp(node a,node b)
{
	return a.r<b.r;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].x);
		sort(a+1,a+1+n,cmp);
		ans=0;
		for(int i=1;i<=n;i++)
			r[i]=a[i].r;
		tr[0].clear(n),tr[1].clear(n);
		tr[0].modify(0,n,0,1,1);
		tr[1].modify(0,n,0,1,1);
		for(int i=1;i<=n;i++)
		{
			int c=a[i].x,end=lower_bound(r+1,r+1+i,a[i].l)-r;
			int tmp=0;
			tmp=tr[c].query(0,n,0,end-1,1);
			tr[c^1].modify(0,n,i,1,tmp); 
			tr[c].updata(0,n,0,end-1,1); 
			ans+=tmp;
			ans%=mod;
		}
		ans++,ans%=mod;
		printf("%lld\n",ans);
	}
	return 0;
}

T4 跳水运动员

T4
什么逆天背景(逃

不会 摆(

标签:int,8.8,ll,long,mod,小结,线段,模拟,define
From: https://www.cnblogs.com/g1ove/p/17625806.html

相关文章

  • 8.7模拟赛小结
    T1转圈圈题目大意:给你一个只含有一个\(1\)的\(01\)串\(S\)每次你可以翻转一段区间为\(k\)的子串且给出\(m\)个禁止位置必须保证\(1\)在任何时刻都不能出现在静止位置上对于每个位置\(i\)给出旋转到\(i\)位置时的最小次数无法旋转到这个位置时输出\(-1\)思考:原题要求我们......
  • 8.11模拟赛小结
    前言最无语的一集T1数对原题给定整数\(L,R\(L\\le\R)\),请计算满足以下条件的整数对\((x,y)\)的数量:\(L\\le\x,y\\le\R\)设\(g\)是\(x,y\)的最大公约数,则满足以下条件:\(g\\neq\1\)且\(\frac{x}{g}\\neq\1\)且\(\frac{y}{g}\\neq\1\)很简单的......
  • 8.8
    今天主要学习了下编程的知识点,看了看视频。出去玩了一圈,上衡水湖溜达了溜达。静态代码块的特点如下:静态代码块类似于一个方法,但它不可以存在于任何方法体中。静态代码块可以置于类中的任何地方,类中可以有多个静态初始化块。 Java虚拟机在加载类时执行静态代码块,所以很多时......
  • 交换机M-LAG知识小结
    M-LAG(MultichassisLinkAggregationGroup)即跨设备链路聚合组,是一种实现跨设备链路聚合的机制,将一台设备与另外两台设备进行跨设备链路聚合,从而把链路可靠性从单板级提高到了设备级,组成双活系统M-LAG的作用:1、增加带宽:将成员交换机的多条物理链路配置成一个聚合组,提高交换机的上行......
  • 【考后总结】8 月 CSP-S 模拟赛 4
    CSP模拟19ItstartedoffsowellTheysaidwemadeaperfectpairIclothedmyselfinyourgloryandyourloveHowIlovedyouHowIcriedTheyearsofcareandloyaltyWerenothingbutashamitseemsTheyearsbeliewelivedthelieIloveyou'......
  • CSP模拟-19
    前言emm.....考场其实想到T2正解的思路了,但是不会优化,导致有些拉胯少了50分。还有就是说数学题我是真不行,向上次\(fengwu\)的筛我不会,这会最简单的容斥想这么老半天学这么老半天都不会,着实是有些废物了。T1十年之约一道很简单的数学题QAQ,但我就是不会,我真服了。首先对于\(......
  • Linux磁盘故障,模拟故障及解决思路方法
    每个分区起始位置都有一个inod表索引节点表(类似于目录表)每一个文件都对应一个编号称为索引节点,如果这个空间文件数太多了,记满了,就说明索引节点表耗尽。故障1 该分区不能正常读写或者说只能读不能写了但是又没有满,就代表文件系统有问题,文件系统有问题需要进行修复命令:故障2:索引......
  • 2023.8.11 模拟赛
    A询问\(L\lei,j\leR\),其中\(\gcd(i,j)\not=1,i,j\)的对数。莫反先求出\(gcd(i,j)\not=1\)的对数,然后再直接调和级数暴力删去\(i,j\)是倍数的对数即可。BP4334[COI2007]Policija考虑建立圆方树。圆方树是怎么样的呢?圆方树是对于每个点双,都建立一个方点,然后......
  • 基于matlab模拟RADAR预警雷达
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 模拟Vue2的v-model
    模拟Vue2的v-model<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><div><!--<buttonid="myBtn">改变user......