A、 牛牛爱字符串
思路
getline读取,把非数字的字符跳过,字符串处理数字,然后删除前导
。
注意特判一下
这种情况
参考代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
signed main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
string s;
while(getline(cin,s)){
for(int i = 0;i < s.size();++i){
if(s[i]>='0'&&s[i]<='9'){
string p="0";
bool f =0;
while(i<s.size()&&s[i]>='0'&&s[i]<='9'){
if(s[i]!='0')f = 1;
if(f)p.push_back(s[i]);
++i;
}
--i;
if(p.size()>1){
for(int i = 1;i < p.size();++i)cout<<p[i];
cout<<" ";
}else cout<<p<<" ";
}
}
cout<<endl;
}
return 0;
}
B、 牛牛爱位运算
思路
对于数 ,它 & 上任何一个数都不会使它变大,所以取个最大值即可。
参考代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
signed main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int t;cin>>t;
while(t--){
int n;cin >> n;
int ans = -1;
for(int i = 1;i <= n;++i){
int x;cin >>x;
ans = max(ans,x);
}
cout<<ans<<endl;
}
return 0;
}
C、 牛牛爱博弈
思路
模拟一下,可以发现一个规律,以 为周期,从1开始,赢赢输赢赢输赢赢输。
参考代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
signed main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int t;
cin >>t;
while(t--){
int n;cin >>n;
bool f = 0;
n %= 3;
if(n==0)f = 0;
else f = 1;
if(f)cout<<"Alan\n";
else cout<<"Frame\n";
}
return 0;
}
D、 牛妹爱数列
思路
简单 DP,
表示把前
位都变成
需要的最小代价,
表示把前
位都变成
需要的最小代价。
转移的方程:
如果
:
如果
:
参考代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
int a[man],dp[man][2];
signed main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int n;scanf("%d",&n);
for(int i = 1;i <= n;++i){
scanf("%d",&a[i]);
}
for(int i = 1;i <= n;++i){
if(a[i]){
dp[i][0] = min(dp[i-1][0],dp[i-1][1]+1) + 1;
dp[i][1] = min(dp[i-1][0]+1,dp[i-1][1]);
}else{
dp[i][0] = min(dp[i-1][0],dp[i-1][1]+1);
dp[i][1] = min(dp[i-1][1],dp[i-1][0]) + 1;
}
}
printf("%d\n",min(dp[n][0],dp[n][1]+1));
return 0;
}
E、牛妹游历城市
思路
首先暴力建图肯定不行的,直接被卡死。
那么想如何优化。
首先我们可以按位操作,把32位看成点,然后对每个点拆点。
即:对于第
位(二进制) 有两个点,
(入点)和
(出点) ,
向
连一个边,边权为
。
然后对于输入的
,如果当前
在第
位(二进制)是
,那么这个点向
连一条边权为
的边,
向该点连一条边权为
的边。
最后跑一遍最短路即可。
正确性:
题目要求的是如果
&
,那么这两个点之间可以连边,边权为
&
。
我们这么建图如何保证所走的边的边权是两个点的
&
呢。
首先假设存在一条最短路:
指向
的,以上建图方式,他们的边权一定是
&
吗?答案是肯定的,假设我们最短路已经搜到
这里了,从
开始去找其他的点,它要走到
,那么它下一步的点一定是
点权二进制位数都有的,且是最低位(符合最短路贪心的思路)。
参考代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
struct node{
int v;
ll w;
bool operator < (const node &a)const{
return w > a.w;
}
};
vector<node>sp[man];
ll a[man];
void add(int u,int v,ll w){
sp[u].push_back(node{v,w});
}
priority_queue<node>q;
ll dis[man];
bool vis[man];int n;
void dij(int s,int num){
for(int i = 1;i <= num;++i)dis[i] = 1e18,vis[i] = 0;
dis[s] = 0;
q.push(node{1,0});
while(q.size()){
node tp = q.top();
q.pop();
if(vis[tp.v])continue;
vis[tp.v] = 1;
for(auto it:sp[tp.v]){
int v = it.v;
ll w = it.w;
if(vis[v])continue;
if(dis[v]>dis[tp.v] + it.w){
dis[v] = dis[tp.v] + it.w;
q.push(node{v,dis[v]});
}
}
}
if(dis[n]==1e18)printf("Impossible\n");
else printf("%lld\n",dis[n]);
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int t;scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i = 1;i <= n;++i){
scanf("%lld",&a[i]);
}
int num = n+1;
for(int i = 0;i <= 32;++i)add(num+i,num+40+i,(1ll<<i));
for(int i = 1;i <= n;++i){
for(int j = 0;j <= 32;++j){
if((a[i]>>j)&1){
add(i,num+j,0);
add(num+40+j,i,0);
}
}
}
dij(1,num+100);
for(int i = 1;i <= num+100;++i){
// cout<<"u:"<<i<<endl;
// for(auto it:sp[i])cout<<it.v<<" ";
// cout<<endl;
sp[i].clear();
}
}
return 0;
}