这场比赛状态不是很好,前面卡了a题,然后其他题都因为其他书写错误,debug了挺久的,然后a了5题,后面一个小时,就基本没a题了,后期比赛一直再推j题的矩阵幂

首先是a题

题面链接:https://www.nowcoder.com/acm/contest/136/A
一开始感觉就是判断一下,是否要掉头,已经掉头是否会使时间更短,但是wa了92%

转念一想,如果小鲲如果先到终点,就不能掉头了,因为会被看到作弊。。这个坑貌似坑了很多人

但是这题的数据挺水的。。有人直接输出l/b-l/a貌似都过了

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;
int main(){
    int a,b,c,d;
    int n,m;
    int l,k;
    cin>>l>>k>>a>>b;
    double t1,t2;
    t1=(double)l/a;
    if(a<b) t2=(double)l/b;
    else{
        int vis=0;
        t2=(double)k/(a-b);
        if(t2<=t1){
        double s=t2*b;
        if(s*2>l) t2=(double)l/b;
        else {
            t2+=(double)s/b;
            vis=1;
        }
        }
        else t2=(double)l/b;
        if(vis==1){
            if(t2*a+k>=l)
                t2=(double)l/b;
        }
    }
    printf("%.2f",t2-t1);
    return 0;
}

然后是b题,模拟,签到题

题目链接:https://www.nowcoder.com/acm/contest/136/B
就是模拟一下状态,然后把状态标记一下,表示当前是上升状态或者是下降状态就OK了

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;
int main(){
    int n,m,t;
    int flag=0;//1表示上升状态,2表示下降状态。
    int sum=0;
    scanf("%d",&t);
    scanf("%d",&m);
    for(int i=1;i<t;i++){
        scanf("%d",&n);
        if(flag==0){
            if(n>m) flag=1;
        }
        else if(flag==1){
            if(n<m){
                flag=2;
            }
        }
        else if(flag==2){
            if(n>m){
                flag=1;
                sum++;
            }
            if(n==m){
                flag=0;
                sum++;
            }
        }
        m=n;
    }
    if(flag==2) sum++;
    printf("%d",sum);
    return 0;
}

c题,树上最长路

题目链接:https://www.nowcoder.com/acm/contest/136/C
题意倒是挺容易理解的,就是找树上的一条路使得该条路最长。

一开始想用dfs直接去搜,但是不会写,然后想到用dp去做找从该点出发的最长路和次长路,然后只需要将最长路和次长路相加就行了

#include<bits/stdc++.h>
using namespace std;
const int N = 1000005;
vector<int>g[N];
int first[N], second[N];
int res = 0;
void dp(int u, int pre)
{
    int k = g[u].size();
    for(int i = 0; i < k; i++)
    {
        if(g[u][i]==pre)continue;
        dp(g[u][i],u);
        if(first[g[u][i]]+1>=first[u])second[u]=first[u],first[u]=first[g[u][i]]+1;
        else if(first[g[u][i]]+1>second[u])second[u]=first[g[u][i]]+1;
    }
    res = max(res, first[u]+second[u]);
    return ;
}
int main()
{
    int n,u,v;
    scanf("%d",&n);
    for(int i=1; i<n; i++)
    {
        scanf("%d %d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dp(1,0);
    printf("%d\n",res+1);
}

d题,字符串操作

题目链接:https://www.nowcoder.com/acm/contest/136/D
离线查询,将每个位置的字符串出现次数存起来就行了,一开始用map存,超时了,然后用数组存就过了

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include <map>
#include<stdlib.h>
using namespace std;

void read(int &x){
    x=0;char c=getchar();
    while(c<'0' || c>'9')c=getchar();
    while(c>='0' && c<='9'){
        x=x*10+c-'0';
        c=getchar();
    }
}
void write(int x){
    if(x==0){putchar(48);return;}
    int len=0,dg[20];
    while(x>0){dg[++len]=x%10;x/=10;}
    for(int i=len;i>=1;i--)putchar(dg[i]+48);
}
    int num[1000005];
    map<char,int>s;
    char ss[1000005];
int main(){
    int n,m;
    read(n);
    read(m);
    scanf("%s",&ss);
    for(int i=1;i<=n;i++){
        s[ss[i-1]]++;
        num[i]=s[ss[i-1]];
    }
    int t;
    for(int i=0;i<m;i++){
        read(t);
        write(num[t]);
        printf("\n");
    }
    return 0;
}

H题,图论

最小生成树裸题,直接套模版

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;

#define maxn 100005
int n, m;

struct arcnode
{
    int vertex;
    int weight;
    arcnode * next;
    arcnode() {}
    arcnode(int v,int w):vertex(v),weight(w),next(NULL) {}
};

struct vernode
{
    int vex;
    arcnode * firarc;
}Ver[maxn];

void Init()
{
    for(int i = 1; i <= n; i++)
    {
        Ver[i].vex = i;
        Ver[i].firarc = NULL;
    }
}

void Insert(int a, int b, int w)
{
    arcnode * q = new arcnode(b, w);
    if(Ver[a].firarc == NULL)
        Ver[a].firarc = q;
    else
    {
        arcnode * p = Ver[a].firarc;
        if(p->vertex == b)
        {
            if(p->weight > w)
                p->weight = w;
            return ;
        }
        while(p->next != NULL)
        {
            if(p->next->vertex == b)
            {
                if(p->next->weight > w);
                    p->next->weight = w;
                return ;
            }
            p = p->next;
        }
        p->next = q;
    }
}
void Insert2(int a, int b, int w)
{
    arcnode * q = new arcnode(b, w);
    if(Ver[a].firarc == NULL)
        Ver[a].firarc = q;
    else
    {
        arcnode * p = Ver[a].firarc;
        q->next = p;
        Ver[a].firarc = q;
    }
}
struct node
{
    int v;
    int key;
    friend bool operator<(node a, node b)
    {
        return a.key > b.key;
    }
};

#define INF 0xfffff
int parent[maxn];
bool visited[maxn];
node vx[maxn];
priority_queue<node> q;
void Prim()
{
    for(int i = 1; i <= n; i++)
    {
        vx[i].v = i;
        vx[i].key = INF;
        parent[i] = -1;
        visited[i] = false;
    }
    vx[1].key = 0;
    q.push(vx[1]);
    while(!q.empty())
    {
        node nd = q.top();
        q.pop();
        if(visited[nd.v])
            continue;
        visited[nd.v] = true;
        arcnode * p = Ver[nd.v].firarc;
        while(p != NULL)
        {
            if(!visited[p->vertex] && p->weight < vx[p->vertex].key)
            {
                parent[p->vertex] = nd.v;
                vx[p->vertex].key = p->weight;
                vx[p->vertex].v = p->vertex;
                q.push(vx[p->vertex]);
            }
            p = p->next;
        }
    }
}

int main()
{
    int a, b ,w;
    cin >> n >> m;
    Init();
    while(m--)
    {
        cin >> a >> b >> w;
        Insert2(a, b, w);
        Insert2(b, a, w);
    }
    Prim();
    int cnt = 0;
    for(int i = 1; i <= n; i++)
        cnt += vx[i].key;
    cout << cnt << endl;
    return 0;
}

J题,线性递推,矩阵快速幂

一开始一直没思路,又不像推公式,就很难受,然后有人说是用矩阵快速幂做,我最近才接触,只以为矩阵快速幂只能求数列中第n项的值,不能求前n项的和,后面发现sum【n】=sum【n-1】+f【n】

然后就可以用矩阵快速幂进行递推,比赛快结束的时候想到,没时间写了,后面比赛结束一发a了。。

 

#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <stack>
#define INF 1e9
using namespace std;
const int maxn=3;
const int mod=1000000007;
struct matrix{
    long long a[maxn][maxn];
    void init(){
        memset(a,0,sizeof(a));
        for(int i=0;i<maxn;i++) a[i][i]=1;
    }
};
matrix mul(matrix a,matrix b){
    matrix ans;
    for(int i=0;i<maxn;++i){
        for(int j=0;j<maxn;++j){
            ans.a[i][j] = 0;
            for(int k=0;k<maxn;++k){
                ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j]+mod)%mod;
            }
        }
    }
    return ans;
}
matrix qpow(matrix a, int n){
    matrix ans;
    ans.init();
    while(n){
        if(n&1) ans = mul(ans, a);
        a=mul(a,a);
        n/=2;
    }
    return ans;
}
int main()
{
    matrix ans,res;
    int n,k,q;
    memset(ans.a,0,sizeof(ans.a));
    memset(res.a,0,sizeof(res.a));
    cin>>n>>k>>q;
    if(n==1){
        cout<<1<<endl;
        return 0;
    }
    ans.a[0][0]=1;ans.a[0][1]=1;ans.a[1][1]=k;
    ans.a[1][2]=1;ans.a[2][2]=1;
    res=qpow(ans,n);
    long long s=res.a[0][0]*1l%mod+res.a[0][1]*1l%mod+res.a[0][2]*q%mod;
    cout<<s%mod-1<<endl;
}