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