牛客小白月赛6
这场比赛状态不是很好,前面卡了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; }