2022.09.13 模拟赛小结
2022.09.13 模拟赛小结
题面
(这个链接只是为了自己方便找,页面设置权限了,不要尝试访问)
更好的阅读体验戳此进入
(建议您从上方链接进入我的个人网站查看此 Blog,在 Luogu 中图片会被墙掉,部分 Markdown 也会失效)
赛时思路
T1
是一道 DP + 最短路,赛时没想到 DP,嗯写了个 Dijk + 随机化微小扰动 + 卡时,当然最后寄掉了。
Code
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define npt nullptr
/******************************
abbr
******************************/
using namespace std;
mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int percent){return rndd(1, 100) <= percent;}
typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
bitset < 110 > wharf[22];
int blocked[22];
template<typename T = int>
inline T read(void);
struct Edge{
Edge* nxt;
int to;
int val;
void* operator new(size_t);
Edge(Edge* nxt, int to, int val):nxt(nxt), to(to), val(val){;}
Edge(void) = default;
}eData[410];
void* Edge::operator new(size_t){static Edge* P = eData; return ++P;}
Edge* head[22];
int N, M, K, E;
bool vis[22];
ll dis[22];
void Dijk(int);
priority_queue <
pair < ll, int > /*distance, vertex*/,
vector < pair < ll, int > >,
// [](pair < int, int > x, pair < int, int > y) ->bool{
// }
greater < pair < ll, int > >
> vert;
int main(){
freopen("plan.in", "r", stdin);
freopen("plan.out", "w", stdout);
N = read(), M = read(), K = read(), E = read();
for(int i = 1; i <= E; ++i){
int f = read(), t = read(), val = read();
if(f == t)continue;
head[f] = new Edge(head[f], t, val);
head[t] = new Edge(head[t], f, val);
}
int D = read();
while(D--){
int p = read(), a = read(), b = read();
for(int i = a; i <= b; ++i)wharf[p][i] = true;
}
for(int i = 1; i <= M; ++i)blocked[i] = wharf[i]._Find_next(0);
ll ans(0);
ll lastcost(-1);
for(int i = 1; i <= N; ++i){
Dijk(i);
ll cost = dis[M];
ans += cost;
if(i != 1 && cost != lastcost)ans += K;
lastcost = cost;
}
while((double)clock() / CLOCKS_PER_SEC < 0.7){
for(int i = 1; i <= M; ++i){
for(auto j = head[i]; j; j = j->nxt){
if(rnddd(10))j->val *= 1.05;
}
blocked[i] = wharf[i]._Find_next(0);
}
ll anss(0);
ll lastcostt(-1);
for(int i = 1; i <= N; ++i){
Dijk(i);
ll costt = dis[M];
anss += costt;
if(i != 1 && costt != lastcostt)anss += K;
lastcostt = costt;
}
ans = min(ans, anss);
}
printf("%lld\n", ans);
// fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}
void Dijk(int day){
bool block[22];
memset(block, false, sizeof(block));
for(int i = 1; i <= M; ++i){
if(day == blocked[i]){
block[i] = true;
if(blocked[i] <= N)blocked[i] = wharf[i]._Find_next(blocked[i]);
}
}
memset(vis, false, sizeof(vis));
for(int i = 1; i <= M; ++i)dis[i] = LLONG_MAX / 2ll - 10ll;
dis[1] = 0ll;
vert.push(make_pair(dis[1], 1));
while(!vert.empty()){
int p;
tie(ignore, p) = vert.top();
vert.pop();
if(vis[p] || block[p])continue;
vis[p] = true;
for(auto i = head[p]; i; i = i->nxt){
if(dis[p] + i->val < dis[i->to]){
dis[i->to] = dis[p] + i->val;
if(!vis[i->to])vert.push(make_pair(dis[i->to], i->to));
}
}
}
}
template<typename T>
inline T read(void){
T ret(0);
short flag(1);
char c = getchar();
while(c != '-' && !isdigit(c))c = getchar();
if(c == '-')flag = -1, c = getchar();
while(isdigit(c)){
ret *= 10;
ret += int(c - '0');
c = getchar();
}
ret *= flag;
return ret;
}
/*
5 5 10 8
1 2 1
1 3 3
1 4 2
2 3 2
2 4 4
3 4 1
3 5 2
4 5 2
4
2 2 3
3 1 1
3 3 3
4 4 5
*/
T2
原题是 LG-P1768 天路。
赛时写了个 $ n $ 次 Dijkstra,然后还是重载的一大堆符号,似乎假掉了,Luogu 上过了一个点其他全部 RE,数据下不了暂时不知道什么原因。
Code
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define npt nullptr
/******************************
abbr
******************************/
using namespace std;
mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
template<typename T = int>
inline T read(void);
struct Node{
int v, p;
Node(int v, int p):v(v), p(p){;}
Node(void) = default;
bool operator < (const Node d)const{/////////////////////
if(!this->p || !this->v)return true;
if(!d.p || !d.v)return false;
double x = (double)this->v / (double)this->p;
double y = (double)d.v / (double)d.p;
return x < y;
}
bool operator > (const Node d)const{/////////////////////
if(!this->p || !this->v)return false;
if(!d.p || !d.v)return true;
double x = (double)this->v / (double)this->p;
double y = (double)d.v / (double)d.p;
return x > y;
}
Node operator + (Node d){
return Node(this->v + d.v, this->p + d.p);
}
void operator = (Node d){
this->p = d.p;
this->v =d.v;
}
};
struct Edge{
Edge* nxt;
int to;
Node val;
void* operator new(size_t);
Edge(Edge* nxt, int to, Node val):nxt(nxt), to(to), val(val){;}
Edge(void) = default;
}eData[21000];
void* Edge::operator new(size_t){static Edge* P = eData; return ++P;}
Edge* head[7500];
int N, M;
bool vis[22];
Node dis[22];
void Dijk(int);
priority_queue <
pair < Node, int >/*value, vertex*/,
vector < pair < Node, int > >,
less < pair < Node, int > >
> vert;
int main(){
freopen("road.in", "r", stdin);
freopen("road.out", "w", stdout);
N = read(), M = read();
for(int i = 1; i <= M; ++i){
int f = read(), t = read(), v = read(), p = read();
if(f == t)continue;
head[f] = new Edge(head[f], t, Node(v, p));
}
Node ans(0, 0);
for(int i = 1; i <= N; ++i){
Dijk(i);
if(dis[i] > ans)ans = dis[i];
// printf("No.%d %.3lf\n", i, (double)dis[i].v / (double)dis[i].p);
}
if(!ans.v || !ans.p)printf("-1\n");
else printf("%.1lf\n", (double)ans.v / (double)ans.p);
// fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}
void Dijk(int S){
memset(vis, false, sizeof(vis));
// memset(dis, 0x3f, sizeof(dis));
for(int i = 1; i <= N; ++i)dis[i].v = 0, dis[i].p = 0x3f3f3f3f;
dis[S] = Node(0, 0);
vert.push(make_pair(dis[S], S));
while(!vert.empty()){
int p;
tie(ignore, p) = vert.top();
vert.pop();
if(vis[p])continue;
vis[p] = true;
if(p == S)vis[p] = false;
for(auto i = head[p]; i; i = i->nxt){
if(dis[p] + i->val > dis[i->to]){
dis[i->to] = dis[p] + i->val;
if(!vis[i->to])vert.push(make_pair(dis[i->to], i->to));
}
}
}
}
template<typename T>
inline T read(void){
T ret(0);
short flag(1);
char c = getchar();
while(c != '-' && !isdigit(c))c = getchar();
if(c == '-')flag = -1, c = getchar();
while(isdigit(c)){
ret *= 10;
ret += int(c - '0');
c = getchar();
}
ret *= flag;
return ret;
}
/*
5 6
1 2 1 1
4 1 6 2
5 4 8 1
2 3 2 2
5 2 4 1
3 5 6 4
*/
T3
差为 1 即可全部覆盖的性质找到了,但是裴蜀定理不太熟悉,没给它转化为 gcd 为 1,所以最后只能打了个暴力。
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define PI M_PI
#define E M_E
#define npt nullptr
/******************************
abbr
******************************/
using namespace std;
mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
#define int ll
template<typename T = int>
inline T read(void);
int N;
int len[310], pri[310];
ll ans(LLONG_MAX);
void bfs(){
queue < pair < int, int > >q;
q.push(make_pair(0, 0));
while(!q.empty()){
int cur, cpri;
tie(cur, cpri) = q.front();
q.pop();
if(cur == 1){
ans = min(ans, cpri);
}
for(int i = 1; i <= N; ++i){
q.push(make_pair(cur + len[i], cpri + pri[i]));
q.push(make_pair(cur - len[i], cpri + pri[i]));
}
if((double)clock() / CLOCKS_PER_SEC > 1.8){
if(ans == LLONG_MAX)printf("-1\n");
else printf("%lld\n", ans);
exit(0);
}
}
}
signed main(){
freopen("jump.in", "r", stdin);
freopen("jump.out", "w", stdout);
N = read();
for(int i = 1; i <= N; ++i)len[i] = read();
for(int i = 1; i <= N; ++i)pri[i] = read();
// int dep(0);
bfs();
// printf("%lld\n", ans);
// fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}
template<typename T>
inline T read(void){
T ret(0);
short flag(1);
char c = getchar();
while(c != '-' && !isdigit(c))c = getchar();
if(c == '-')flag = -1, c = getchar();
while(isdigit(c)){
ret *= 10;
ret += int(c - '0');
c = getchar();
}
ret *= flag;
return ret;
}
T4
我不会
正解
T1
还挺显然的,简单改了一下没过,咕咕咕
T2
大概是二分答案然后 SPFA 找环,emmmm,这个找时间再弄一下,SPFA 没怎么写过,暂时先咕掉。
T3
正解是状压 DP,因为质因数最多好像就八个。不过这道题可以用 map 优化直接切掉,并且复杂度似乎还是正确的。。。
T4
拆点 + 费用流,挺难我不会,还得再看看费用流。
UPD
update-2022_09_13 初稿