A. Left-handers, Right-handers and Ambidexters
水题,AC代码如下:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl;
const int MAXN = 105;
const int MOD = 1e9+7;
int main()
{
int l, r, a;
while(cin>>l>>r>>a)
{
int del = max(l,r) - min(l,r);
if(a>=del)
{
a -= del;
int res = max(l,r)*2;
res += a/2*2;
cout<<res<<endl;
}
else
{
cout<<(min(l,r)+a)*2<<endl;
}
}
return 0;
}
水题,AC代码如下:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl;
const int MAXN = 100005;
const int MOD = 1e9+7;
int mes1[MAXN], mes2[MAXN];
int n, m;
void gogogo(int& p1, int& s1, int& p2, int& s2)
{
while(s1!=s2)
{
if(s1<s2) s1 += mes1[++p1];
else s2 += mes2[++p2];
}
}
int main()
{
FSIO;
while(cin>>n>>m)
{
for(int i=1;i<=n;++i) cin>>mes1[i];
for(int i=1;i<=m;++i) cin>>mes2[i];
int cur1 = 1;
int cur2 = 1;
int cs1 = mes1[cur1];
int cs2 = mes2[cur2];
int res = 0;
while(cur1<=n||cur2<=m)
{
if(cs1 == cs2) { res++; cur1++; cur2++; cs1 = mes1[cur1]; cs2 = mes2[cur2];}
else
{
gogogo(cur1, cs1, cur2, cs2);
}
}
cout<<res<<endl;
}
return 0;
}
题意:定义了一种zebra串,从0开始到0结束,中间部分为0、1交替序列,如010,01010。要求划分一个01序列,若可以划分则输出,否则输出-1。
思路:使用vector存储每一个子串的长度,并且使用两个“单身汉”队列(顾名思义,即需要和0或者1匹配的)存储对应子串的下标。这样只需要遍历一遍原串即可。
AC代码如下:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl;
const int MAXN = 200005;
const int MOD = 1e9+7;
string ss;
vector<int> res[MAXN];
queue<int> bachelor0, bachelor1;
int cnt1, cnt0;
int ans;
int solve()
{
if(ss[0]=='1') return 0;
while(!bachelor0.empty()) bachelor0.pop();
while(!bachelor1.empty()) bachelor1.pop();
for(int i=0;i<ss.length();++i)
{
if(ss[i]=='0')
{
if(bachelor1.size()==0)
{
ans++;
res[ans].push_back(i);
bachelor0.push(ans);
}
else
{
int tmp = bachelor1.front();
res[tmp].push_back(i);
bachelor0.push(tmp);
bachelor1.pop();
}
}
else
{
if(bachelor0.size()==0) return 0;
else
{
int tmp = bachelor0.front();
res[tmp].push_back(i);
bachelor1.push(tmp);
bachelor0.pop();
}
}
}
if(bachelor1.size()>0) return 0;
else return 1;
return 1;
}
int main()
{
FSIO;
while(cin>>ss)
{
for(int i=0;i<MAXN;++i) res[i].clear();
ans = 0;
if(solve())
{
cout<<ans<<endl;
for(int i=1;i<=ans;++i)
{
cout<<res[i].size();
for(int j=0;j<res[i].size();++j)
cout<<" "<<res[i][j]+1;
cout<<endl;
}
}
else cout<<-1<<endl;
}
return 0;
}
题意:设定了一种数组操作,现在给你n和q个询问,询问某位置上数是多少。
思路:对于某数字x,若x <= (n+1)/2,那么它在数组中的位置为 2*x - 1,故最后数组中奇数位的判断使用这个公式即可。
对于x > (n+1)/2,打表发现,x位置的第t次移动为(2*(n-x)-1) * 2^t,
利用等比数列公式即可计算出经过t次移动后x的位置为 (2*x-1) - (2*(n-x) -1) * (2^(t+1) - 1)。
设第t次移动之前位置为 p_0, 移动之后位置为 p_1,那么
p_0 = p_1 + (2*(n-x)-1) * 2^t
= p_1 + (2*n - p_1)/2 // 代入p_1位置公式可以推出。
由此构建出递推式, p_0 = n + p_1/2 ,利用递归方法即可求解。
AC代码如下:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl;
const int MAXN = 200005;
const int MOD = 1e9+7;
long long n;
long long solve(long long pos)
{
if(pos%2) return (pos+1ll)/2ll;
else return solve(n+pos/2ll);
}
int main()
{
FSIO;
int q;
long long x;
while(cin>>n>>q)
{
for(int i=1;i<=q;++i)
{
cin>>x;
cout<<solve(x)<<endl;
}
}
return 0;
}