[牛客小\白月赛40] A, D, E, F, G, I
不是很理解CSDN连小白(标题违规???)都容不下了么
A | 数字游戏https://ac.nowcoder.com/acm/contest/11217/A |
用到了非递归快速幂(怕超时)和位运算
#include<stdio.h>
typedef long long ll;
ll Quick_pow(int a,int n)
{
int ans = 1;
while(n)
{
if(n&1)
ans *= a;
a *= a;
n >>= 1;
}
return ans;
}
int main()
{
int t, x;
scanf("%d",&t);
while(t--)
{
int cnt=0;
scanf("%d",&x);
int y=x;
while(y)
{
int f=y;
int cnt1=0,cntAll=0;;
while(f){
if(f&1) cnt1++;
f >>= 1;
cntAll++;
}
if(cnt1&1){
if(y&1) y--;
else y ++;
}else{
y-=Quick_pow(2,cntAll-1);
}
cnt++;
}
printf("%d\n",cnt);
}
return 0;
}
D | 优美字符串https://ac.nowcoder.com/acm/contest/11217/D |
签到题, 相邻重复数量+字符串长度
#include<iostream>
using namespace std;
int main()
{
int t;
cin >> t;
string s;
while(t--)
{
cin >>s;
int cnt = 0;
for(int i = 0; i < s.length()-1;i ++)
if(s[i]==s[i+1]) cnt++;
cout << s.length()+cnt <<endl;
}
return 0;
}
E | 分组https://ac.nowcoder.com/acm/contest/11217/E |
二分, 二分尽可能多的小组人数(即题中的n), 通过限定组数更新左右区间, 最后需要验证组数是否满足
#include<iostream>
using namespace std;
const int N = 1e5+10;
int n, m;
int cnt[N];
int devide(int h)
{
int sum = 0;
for(int i = 1; i <= n; i++)
if(cnt[i])
sum += (cnt[i]+h-1)/h; //上取整
return sum<=m;
}
int main()
{
cin >> n >> m;
int x;
for(int i = 0; i < n; i ++)
{
scanf("%d", &x);
cnt[x]++;
}
int l = 1, r = n;
while(l<r)
{
int mid = (l + r)>>1;
if(devide(mid)) r = mid;
else l = mid + 1;
}
if(devide(r)) cout << r;
else cout << "-1";
return 0;
}
F | 过桥https://ac.nowcoder.com/acm/contest/11217/F |
bfs + 邻接表
从终点反向奔赴,利用bfs更新最短距离
#include<iostream>
#include<cstring>
using namespace std;
const int N = 2010, M = N * N << 1;
int n, a[N];
int h[N],e[M],ne[M],idx;
int step[N];
int q[M];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int bfs(int u)
{
memset(step, -1, sizeof step);
int front = -1, rear = -1;
step[u] = 0;
q[++rear] = u;
while(front<=rear)
{
int t = q[++front];
for(int i = h[t]; i != -1; i = ne[i]){
int j = e[i];
if(step[j] == -1){
q[++rear] = j;
step[j] = step[t]+1;
}
}
}
return step[1];
}
int main()
{
cin >> n;
memset(h, -1, sizeof h);
for(int i = 1; i <= n; i ++)
{
scanf("%d", &a[i]);
//双向奔赴,为正为负都看作是反向可达
if(a[i]>0){
int r = min(n, a[i]+i);
for(int j = i+1; j <= r; j++) add(j,i);
}else{
int l = max(1, a[i]+i);
for(int j = 1; j <= l; j++) add(j,i);
}
}
cout << bfs(n);
return 0;
}
G | 空调遥控https://ac.nowcoder.com/acm/contest/11217/G |
前缀和, 注意控制区间别越界
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e6+10;
int cnt[N],s[N];
int main()
{
int n,p,res=0;
cin>>n>>p;
int x;
for(int i = 0 ; i < n; i++){
scanf("%d",&x);
cnt[x] ++;
}
for(int i = 1 ; i <= n; i++){
cnt[i] += cnt[i-1];
}
for(int i = 1 ; i <= n; i++){
int t = cnt[min(n, i+p)] - cnt[max(0,i-p-1)];//求区间和
if(res < t) res = t;
}
cout << res;
}
I | 体操队形https://ac.nowcoder.com/acm/contest/11217/I |
求top序的数量, n≤10直接爆搜
#include<iostream>
using namespace std;
const int N = 11;
int n, res;
int a[N], in[N], st[N];
void dfsTop(int u)
{
if(u == n){
res ++;
return ;
}
for(int i = 1; i <= n; i ++)
{
if(!st[i] && !in[i])//入度为零且未访问
{
if(i!=a[i])
in[a[i]]--;
st[i] = 1;
dfsTop(u+1);
st[i] = 0;
if(i!=a[i])
in[a[i]]++;
}
}
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
if(i!=a[i]) in[a[i]]++;
}
dfsTop(1);
cout << res;
return 0;
}
本文来自博客园,作者:泥烟,CSDN同名, 转载请注明原文链接:https://www.cnblogs.com/Knight02/p/15799043.html