2024.11.21模拟赛(*^▽^*)

今天照常七点半左右到学校,结果入门发现氛围不对。打开手机,发现题目压缩包已经发了,我当时就是一个问号。

(一定是刚开始耽误的几分钟耽误我写T2了!!!)

然后就开始写题。这套题的难度对于我还好,不会出现打完暴力只能摆烂的情况。

(但出现了先躺尸式思考然后疯狂打暴力的情况)

T1第一眼看着花里胡哨,其实就是一个大除法;T3T4的暴力都很好打;T2思考了挺久,但是………………思路钻进死胡同里了,最后也只想出了部分分的做法。最后两个小时打了T4T3的暴力,本来我T3可以再优一些的,但是线段树写挂了调试了很久,最后时间不够了才转成更加暴力的写法。T1 100分,T2 20分,T3 50分,T4 75分,总分245,挂了-35分(oj上分数更少、排名更加靠后)

嘻嘻 按照评测机的大水数据的分算了话 我这次考了本机房第一!

作业链接


T1【多项式】

题目大意:

分别给出两个多项式的系数\(H,G\),已知多项式\(H\)\(G\)\(F\)的乘积,求\(F\)的系数。(\(F,G\)的项数\(n\leqslant 2000\))

解题思路:

直接模拟大除法即可。

简单的小代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=3010;
int m,g[N];
int k,h[N];
int f[N];

signed main()
{	
	scanf("%lld",&m);
	for (int i=m;i>=1;i--) scanf("%lld",&g[i]);
	scanf("%lld",&k);
	for (int i=k;i>=1;i--) scanf("%lld",&h[i]);
	
	for (int i=1;i+m-1<=k;i++)
	{
		f[i]=h[i]/g[1];
		h[i]=0;
		int x=f[i];
		for (int j=1;j<=m;j++) h[i+j-1]=h[i+j-1]-x*g[j];
	}
	
	printf("%lld\n",k-m+1);
	for (int i=k-m+1;i>=1;i--) printf("%lld ",f[i]);
	return 0;
}

T2【撑杆跳】

题目大意:

给出\(n\)张卡片,对于每张卡片\(i\)有两个属性\(l_{i},c_{i}\),其中\(l_{i}\)表示可以向前、向后跳\(l_{i}\)的距离,\(c_{i}\)表示拥有这张卡片的代价。刚开始在位置\(0\),要求选择若干个卡片,使得可以要到任何位置并且花费最少,输出最小花费,若无法则输出\(-1\)\((1\leqslant n\leqslant 300,1\leqslant l_{i}\leqslant 10^{9},1\leqslant c_{i}\leqslant 10^{5})\)

解题思路:

我连绿题都切不了,我太菜了www

观察样例可以发现,若要选择方案合法,对于所有被选卡片的最大公因数一定为1。(我不会证,好像和裴蜀定理有关。本人感性理解为:若选择的若干个数的最大公因数 \(g>1\),那么无论怎样跳跃一定只能跳到\(g\)的倍数的地方,无法跳到全部。)

再观察数据范围,容易想到\(dp\)。设\(dp\)方程式\(f_{i,j}\)表示从前\(i\)个数中选,选择数的最大公因数为\(j\)的最小花费。这样了话,\(dp\)转移方程式即为$$f_{i,gcd(j,k)}=min(f_{i,gcd(j,k)},f_{i-1,j}+c_{i})$$

于是乎兴奋地去看数据范围,看到\(l_{i}\)的值域后瞬间泄气

但是注意到\(l_{i}\)的值域,需要优化。

于是就开始瞪,感觉第一维或许可以不要。

继续瞪,越瞪越像\(dij\)中的\(dis_{v}=min(dis_{u},dis_{v}+w)\)好像是叫三角形不等式?

然后就再次想到万能的\(dijkstra\)算法(好吧我刚开始没想到)。将最大公因数设为点的编号,边权即为\(c_{v}\)。因为不好搞的值域,所以\(dis,vis\)数组都用\(map\)来搞。

复杂度不知道,反正能过(就很神奇)

然后就出现了

神奇的小代码
#incIude <bits/stdc++.h>
#define int long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;
const int N=310;
const int inf=0x3f3f3f3f3f3f3f3f;
int T;
int n;
int v[N],c[N];

unordered_map <int,int> dis;
unordered_set <int> vis;
priority_queue < pii,vector <pii>,greater<pii> > q;
int gcd(int x,int y)
{
	if (!y) return x;
	return gcd(y,x%y);
}
void dijkstra()
{
	dis.clear();
	vis.clear();
	while (!q.empty()) q.pop();
	dis[0]=0;
	q.push(mp(0,0));
	while (!q.empty())
	{
		int u=q.top().second;
		q.pop();
		if (u==1) break;
		if (vis.find(u)!=vis.end()) continue;
		vis.insert(u);
		
		for (int i=1;i<=n;i++)
		{
			int y=gcd(v[i],u);
			if (dis.find(y)==dis.end()) dis[y]=inf;
			if (dis[y]>dis[u]+c[i])
			{
				dis[y]=dis[u]+c[i];
				q.push(mp(dis[y],y));
			}
		}
	}
}
signed main()
{
	scanf("%lld",&T);
	while (T--)
	{
		scanf("%lld",&n);
		for (int i=1;i<=n;i++) scanf("%lld",&v[i]);
		for (int i=1;i<=n;i++) scanf("%lld",&c[i]);
		
		dijkstra();
		
		if (dis.find(1)!=dis.end()) printf("%lld\n",dis[1]);
		else printf("-1\n");
	}
	return 0;
}

唉我好菜啊 www


posted @ 2024-11-21 20:23  还是沄沄沄  阅读(11)  评论(1编辑  收藏  举报