A
- 题意: 给出一个二进制数,求比这个数小的四的整次方倍数的个数
- 思路: 直接求长度除2,若长度为奇数且除最高次位外其他位数有1,则答案加1.
二进制数的每两位代表一个四进制数
B
- 题意: 一个序列,其中的每个数要么是该序列中一个数的两倍,要么是1,给出不同数字的最大,最小个数(l,r),求这个序列和的最大值和最小值
- 思路: 最小和肯定前面全是1后面l-1个依次递增2倍,最大和肯定前面r个递增到最大,后面n-r个全是最大的数
C
- 题意: 给出一个无权有向图,在给出一个路径,让你进行压缩,使得压缩后的路径长度与压缩前的路径长度相等.
- 思路: 能够被压缩,则一定是最短路,将非最短路的路径记录下来即可,而非最短路肯定能找到一个中转点(终点前一个点),使得起点到中转点(若不是最短路,则该点不会被压缩),中转点到终点都是最短路. 求最短路,当前起始点为q,向后找到第一个距离大于最短路距离的点p,将p前面的点加入到路径中.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int M = 1e6+10;
const int N = 120;
int n,m;
int p[M];
int G[N][N];
char buf[N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s",buf+1);
for(int j=1;j<=n;++j){
if(buf[j]=='1') G[i][j] = 1;
else G[i][j] = INF;
}
}
scanf("%d",&m);
for(int i=1;i<=m;++i) scanf("%d",&p[i]);
for(int k=1;k<=n;++k){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
G[i][j] = min(G[i][j],G[i][k]+G[k][j]);
}
}
}
int st = p[1],po = 1;
vector<int> ans;
ans.push_back(st);
for(int i=2;i<=m;++i){
if(i-po != G[st][p[i]] || p[i]==st){
ans.push_back(p[i-1]);
st = p[i-1];
po = i-1;
}
}
ans.push_back(p[m]);
printf("%d
",ans.size());
for(auto i:ans){
printf("%d ",i);
}
return 0;
}
题目要求两个相同点不能同时出现,要特判