模拟赛简要题解
一下题目均可在loj上找到
10178. 「一本通 5.5 例 4」旅行问题
简单题,将n扩大到2 * n,单调队列即可,注意正反向.
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=2000005;
ll sum[N];
int p[N],d[N],que[N],ok[N];
int n;
inline int read() {
int x = 0,f = 1;char c = getchar();
while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
return x * f;
}
void DP1()
{
int q1 = 1,q2 = 0;
for (int i = 1; i <= n; ++ i){
while (q1 <= q2 && sum[que[q2]] >= sum[i]) -- q2;
que[++ q2]=i;
}
for (int i = n + 1; i <= n * 2; ++ i){
while (q1 <= q2 && sum[que[q2]] >= sum[i]) -- q2;
que[++ q2] = i;
while (q1 <= q2 && que[q1] <= i - n) ++ q1;
if (sum[que[q1]] >= sum[i - n]) ok[i-n] = 1;
}
}
void DP2()
{
int q1 = 1,q2 = 0;
for (int i = n * 2; i > n; -- i){
while (q1 <= q2 && sum[que[q2]] >= sum[i]) -- q2;
que[++ q2] = i;
}
for (int i = n; i; -- i){
while (q1 <= q2 && sum[que[q2]] >= sum[i]) -- q2;
que[++ q2] = i;
while (q1 <= q2 && que[q1] >= i + n) ++ q1;
if (sum[que[q1]] >= sum[i + n]) ok[i] = 1;
}
}
int main()
{
n = read();
for(int i = 1;i <= n;++ i) {
p[i + n] = p[i] = read(),d[i + n] = d[i] = read();
sum[i] = sum[i - 1] + p[i - 1] - d[i - 1];
}
for(int i = n + 1;i <= 2 * n;++ i)
sum[i] = sum[i - 1] + p[i - 1] - d[i - 1];
DP1();
for(int i = n * 2 ;i; -- i)
sum[i] = sum[i + 1] + p[i + 1] - d[i];
DP2();
for(int i = 1;i <= n;++ i)
ok[i] ? puts("TAK") : puts("NIE");
return 0;
}
10078. 「一本通 3.2 练习 4」新年好
简单题,spfa跑六边最短路,全排列枚举即可.
#include
#include
#include
#include
const int maxN = 5e4 + 7;
const int maxM = 1e5 + 7;
using namespace std;
int ke_dis[maxN][7];
queue q;
bool vis[maxN];
int dis[maxN];
int Q[7],n,m;
struct Node {
int v,nex,w;
}Map[maxM << 1];
int head[maxN],num;
void add_Node(int u,int v,int w) {
Map[++ num] = (Node) {v,head[u],w};
head[u] = num;
return ;
}
inline int read() {
int x = 0,f = 1;char c = getchar();
while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
return x * f;
}
void spfa(int beg,int bh) {
memset(dis,0x3f,sizeof(dis));
dis[beg] = 0;
q.push(beg);
vis[beg] = true;
while(!q.empty()) {
int p = q.front();q.pop();vis[p] = false;
for(int i = head[p];i;i = Map[i].nex) {
int v = Map[i].v;
if(dis[v] > dis[p] + Map[i].w) {
dis[v] = dis[p] + Map[i].w ;
if(!vis[v]) {
q.push(v);
vis[v] = true;
}
}
}
}
for(int i = 1;i <= n;++ i)
ke_dis[i][bh] = dis[i];
return;
}
long long ans;
bool is_ch[7];
int ch[7];//五个亲戚走的顺序 , 只是编号 Q[编号] 是车站的编号
//特殊的Q[0] = 1 亲戚应该为1
void work() {
long long sum = 0;
for(int i = 1;i <= 5;++ i) {
sum += (long long) ke_dis[Q[ch[i - 1]]][ch[i]];
}
ans = min(ans,sum);
}
void dfs(int tot) {
if(tot == 6) work();
for(int i = 1;i <= 5;++ i) {
if(!is_ch[i]) {
ch[tot] = i;is_ch[i] = true;
dfs(tot + 1);
is_ch[i] = false;
}
}
}
int main() {
n = read();m = read();
Q[0] = 1;
for(int i = 1;i <= 5;++ i)
Q[i] = read();
for(int i = 1,u,v,w;i <= m;++ i) {
u = read();v = read();w = read();
add_Node(u,v,w);
add_Node(v,u,w);
}
for(int i = 0;i <= 5;++ i)
spfa(Q[i],i);
ans = 1e12;
dfs(1);
printf("%lld", ans);
return 0;
}
#10220. 「一本通 6.5 例 2」Fibonacci 第 n 项
最简单的题目.
套一个矩阵乘法即可.
#include
#include
#include
#define ll long long
using namespace std;
struct Node {
ll w[4][4];
Node() {
memset(w,0,sizeof(w));
}
};
ll n,m;
Node mul(Node a,Node b) {
Node c;
for(ll i = 1;i <= 2;++ i) {
for(ll j = 1;j <= 2;++ j) {
for(ll k = 1;k <= 2;++ k) {
c.w[i][j] = ( c.w[i][j] + a.w[i][k] * b.w[k][j] ) % m;
}
}
}
return c;
}
void fast_pow(ll b) {
Node a,ans;
a.w[1][1] = a.w[1][2] = a.w[2][1] = 1;
ans.w[1][1] = ans.w[2][2] = 1;
for(;b;b >>= 1,a = mul(a,a) ) {
if(b & 1) ans = mul(ans,a);
}
Node tmp;
tmp.w[1][1] = tmp.w[1][2] = 1;
ans = mul(tmp,ans);
printf("%lld", ans.w[1][1]);
return ;
}
int main() {
scanf("%lld%lld",&n,&m);
if(n == 1) {puts("1");return 0;}
if(n == 2) {puts("1");return 0;}
fast_pow(n - 2);
return 0;
}
考试收获
题目一定要读好,读准.
不然像这次, \(300 -> 220\)
暴力一定要打.
不然\(250\)分的暴力.
提高自己的码力和代码查错水平
现在,Gzy我现在要开始认真了呢.