DTOJ 2023.02.11 测试 题解
DTOJ 2023.02.11 测试 题解
2023 省选模拟 Round #12
还行 T2 想到了,但是没写,我觉得写了也不一定写得出来,挺妙的
T1
题意
http://59.61.75.5:18018/p/5455
铃是一个爱玩游戏的女孩子。
她在游戏中想要炼制一种稀有合金 —— 这需要
她准备好矿石后建造了
如果把每个熔炉炼出的金属收集起来,有了全部
答案可能很大,请对
题解
水题 不知道为什么放测试里了
可以独立考虑每种金属,每种都不能是空集,所以是
听说有人在容斥和二项式反演。
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int P = 998244353;
int n,k;
int qpow(int a, int b)
{
int r=1;
for(; b; b>>=1,a=(ll)a*a%P) if(b&1) r=(ll)a*r%P;
return r;
}
int main()
{
scanf("%d%d",&n,&k);
printf("%d\n",qpow(qpow(2,k)-1,n));
return 0;
}
T2
题意
http://59.61.75.5:18018/p/5456
给定一个
给定
对于所有数据,满足
题解
暴力拓扑很好想,注意拓扑序一定是
注意 DAG 上的最短路可以拓扑排序
正解也很好想
注意到你可以带着
这样子每一个点的最短路一定是
容易发现这时候
于是你维护凸包,一遍拓扑排序一遍回答,
这看着太对了吧,分析一下复杂度
于是我选择写暴力(
事实上有一个很厉害的结论,竟然是论文题,结论是这样的:
证明也不难,我觉得还挺妙的
于是你的复杂度就是
具体怎么合并凸包:使用类似归并排序的东西,详细看代码
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e4+5, M = 1e5+5, Rl = 1005, N23 = 1500, inf = 1e9;
int n,m,q;
struct edge { int v,c; };
vector<edge> g[N];
struct pnt
{
int x,y;
friend bool operator< (const pnt &A, const pnt &B) { return A.x<B.x or (A.x==B.x and A.y<B.y); }
friend pnt operator- (const pnt &A, const pnt &B) { return {A.x-B.x,A.y-B.y}; }
friend ll operator* (const pnt &A, const pnt &B) { return (ll)A.x*B.y-(ll)A.y*B.x; }
} tb[Rl+5][N23];
int sz[Rl+5];
struct Misaka { int a,b,x,ans,id; } Q[N];
pnt w[N23];
int nw;
void psh(const pnt &p)
{
while(nw>1 and (w[nw]-w[nw-1])*(p-w[nw])<=0) nw--;
if(nw and w[nw].x==p.x) w[nw]=min(w[nw],p);
else if(!nw or w[nw].y>p.y) w[++nw]=p;
}
void update(int v, int u, int col)
{
nw=0;
int umod=u%Rl,vmod=v%Rl;
for(int cv=1,cu=1; cv<=sz[vmod] or cu<=sz[umod]; )
{
auto tu=tb[umod][cu],tv=tb[vmod][cv];
if(col) tu.y++; else tu.x++;
if(cv>sz[vmod]) psh(tu),cu++;
else if(cu>sz[umod]) psh(tv),cv++;
else
{
if(tu.x<tv.x) psh(tu),cu++;
else psh(tv),cv++;
}
}
sz[vmod]=nw;
for(int i=1; i<=sz[vmod]; i++) tb[vmod][i]=w[i];
}
int main()
{
scanf("%d%d",&n,&m); for(int i=1,u,v,c; i<=m; i++) scanf("%d%d%d",&u,&v,&c),g[u].push_back({v,c});
scanf("%d",&q); for(int i=1; i<=q; i++) scanf("%d%d%d",&Q[i].a,&Q[i].b,&Q[i].x), Q[i].ans=inf,Q[i].id=i;
sort(Q+1,Q+q+1, [&] (const Misaka &A, const Misaka &B) { return A.x<B.x or (A.x==B.x and A.a*B.b>B.a*A.b); });
int Qc=1; tb[1][++sz[1]]={0,0};
for(int i=1; i<=n; i++)
{
while(Q[Qc].x<i) Qc++;
for(auto e:g[i]) update(e.v,i,e.c);
int imod=i%Rl;
/*printf("i=%d: ",i);
for(int j=1; j<=sz[imod]; j++) printf("(%d %d) ",tb[imod][j].x,tb[imod][j].y);
puts("");*/
int tc=1;
while(Qc<=q and Q[Qc].x==i)
{
while(tc<sz[imod] and (tb[imod][tc+1]-tb[imod][tc])*(pnt){Q[Qc].b,-Q[Qc].a}>=0) tc++;
// printf("qa=%d qb=%d qx=%d\n",Q[Qc].a,Q[Qc].b,Q[Qc].x);
// printf("tc=%d tx=%d ty=%d\n",tc,tb[imod][tc].x,tb[imod][tc].y);
Q[Qc].ans=min(Q[Qc].ans,Q[Qc].a*tb[imod][tc].x+Q[Qc].b*tb[imod][tc].y); Qc++;
}
sz[imod]=0;
}
sort(Q+1,Q+q+1, [&] (const Misaka &A, const Misaka &B) { return A.id<B.id; });
for(int i=1; i<=q; i++) printf("%d\n",Q[i].ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!