月考简要题解

模拟赛简要题解

一下题目均可在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我现在要开始认真了呢.

转载于:https://www.cnblogs.com/tpgzy/p/9768574.html

你可能感兴趣的:(月考简要题解)