A. A+B?
题意:
t组测试每组给出以a+b的形式给出算式,求a+b的值。(a,b都是0~9)
代码:
t=int(input())
for i in range(t):
s=input()
print(eval(s))
B. Matrix Rotation
题意:
t组测试每组给一个2*2的矩阵,你可以把矩阵顺时针旋转90度(可以做多次)。问能否使得矩阵满足对于每一行和每一列第一个元素都小于第二个元素。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include<bitset>
#include<list>
#include <algorithm>
#define pii pair<int,int>
#define se second
#define fi first
#define rep(i,a,b) for (int i=a;i<b;++i)
#define per(i,a,b) for (int i=a;i>b;--i)
#define mid ((l+r)>>1)
#define lson(root) ((root)<<1)
#define rson(root) (((root)<<1)|1)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define endl '\n'
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const LL INF=0x3f3f3f3f;
const LL MOD=1e9+7;
const int N=3003;
const int M=3003;
void solve(){
int flag=0;
int a,b,c,d;
cin>>a>>b>>c>>d;
if (a<b && c<d && a<c && b<d) flag=1;
if (c<a && d<b && c<d && a<b) flag=1;
if (d<c && b<a && d<b && c<a) flag=1;
if (b<d && a<c && b<a && d<c) flag=1;
if (flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
return ;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("title.in","r",stdin);
freopen("title.out","w",stdout);
#endif
// ios::sync_with_stdio(false);
// cin.tie(0);cout.tie(0);
int _=1;
cin>>_;
// cout<<_<<endl;
// scanf("%d",&_);
while (_--) solve();
// rep(i,1,_+1){
// cout<<"Case "<<i<<": ";
// solve();
// }
return 0;
}
C. Different Differences
题意:
t(1≤t≤819)组测试每组给定k和n (2≤k≤n≤40),构造一个含有k个元素的严格递增序列a,1<=ai<=n,使得序列[a2−a1,a3−a2,…,ak−ak−1]所包含不同数的个数最多。
思路:
就是要求相邻数距离的不同个数最大。如果n=k,只能构造1,2,3...n,相邻数之间的距离都为1;如果n-k=1,就可以把一个距离改为2,得到不同个数多一个;若n-k=3,把一个距离改为2,一个改为3,得到不同个数为3。由此类推可知如果n-k刚好是t*(t+1)/2的形式,可以得到t+1个不同的个数。
首先找出t*(t+1)<=2*(n-k)最大的t,说明最多可以修改多少个距离。先构造前t+1个数,即1,3,6,10...i*(i+1)/2。这样保证达到最大不同个数了,后面就递增构造就可以了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include<bitset>
#include<list>
#include <algorithm>
#define pii pair<int,int>
#define se second
#define fi first
#define rep(i,a,b) for (int i=a;i<b;++i)
#define per(i,a,b) for (int i=a;i>b;--i)
#define mid ((l+r)>>1)
#define lson(root) ((root)<<1)
#define rson(root) (((root)<<1)|1)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define endl '\n'
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const LL INF=0x3f3f3f3f;
const LL MOD=1e9+7;
const int N=45;
const int M=3003;
int a[45];
void solve(){
int k,n;
cin>>k>>n;
int t=n-k,d=0;
while(d*(d+1)<=2*t) ++d;
rep(i,1,d+1) a[i]=i*(i+1)/2;
rep(i,d+1,k+1) a[i]=a[i-1]+1;
rep(i,1,k+1) cout<<a[i]<<" ";
cout<<endl;
return ;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("title.in","r",stdin);
freopen("title.out","w",stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int _=1;
cin>>_;
// cout<<_<<endl;
// scanf("%d",&_);
while (_--) solve();
// rep(i,1,_+1){
// cout<<"Case "<<i<<": ";
// solve();
// }
return 0;
}
D. Absolute Sorting
题意:
t组(1≤t≤2⋅10^4)测试,每组给定长度为n(2≤n≤2⋅10^5)的数组a(1≤ai≤10 ^8)。只能进行一次操作,选一个数,把每个ai变成|ai-x|。问x是多少的时候可以将a排好序(即a1≤a2≤⋯≤an)。不存在输出-1.
思路:
考虑序列中的逆序对ai>aj (i<j),考虑x至少为多少才能使得ai>=aj。此时x一定会比aj大,如果x大于ai显然满足,我们考虑x<=ai的情况,去掉绝对值就是:
即:
对于一个所有的逆序对都需要满足上式,所有求出ai+aj最大的逆序对就是x的最小值,用归并就可以做。求出后在求出操作后的a检查一遍合不合法就可以了。
为什么x要尽量选小的?因为ai<aj (i<j),x不能超过,否则就变成逆序对了。所以越小越好。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include<bitset>
#include<list>
#include <algorithm>
#define pii pair<int,int>
#define pll pair<LL,LL>
#define pil pair<int,LL>
#define pli pair<LL,int>
#define pdd pair<db,db>
#define se second
#define fi first
#define endl '\n'
#define rep(i,a,b) for (register int i=a;i<b;++i)
#define per(i,a,b) for (register int i=a;i>b;--i)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define db double
#define eps 1e-9
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MOD=1e9+7;
const int N=2e5+10;
int a[N],b[N],c[N],mx;
void merge(int l,int r)
{
if(l>=r) return;
int mid=l+r>>1;
merge(l,mid),merge(mid+1,r);
int i=l,j=mid+1;
rep(k,l,r+1)
if(j>r||i<=mid&&c[i]<=c[j]) b[k]=c[i++];
else{
if(mid-i+1>0) mx=max(mx,(c[mid]+c[j])/2+(c[mid]+c[j])%2);
b[k]=c[j++];
}
rep(k,l,r+1) c[k]=b[k];
}
void solve()
{
int n;
cin>>n;
rep(i,0,n) cin>>a[i],c[i]=a[i];
mx=0;
merge(0,n-1);
if(mx==0){
cout<<0<<endl;
return;
}
rep(i,0,n) a[i]=abs(a[i]-mx);
rep(i,1,n){
if(a[i-1]>a[i]){
cout<<-1<<endl;
return;
}
}
cout<<mx<<endl;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("title.in","r",stdin);
freopen("title.out","w",stdout);
#endif
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _=1;
cin>>_;
while(_--){
solve();
}
return 0;
}
E. Permutation Game
题意:
给定一个n的排列,两个人玩游戏,第一个人使排列变成正序获胜,第二个人使排列变成倒序获胜,初始所有数都是红色,且保证没有排好的情况。每一轮一个人可以:1.把所有蓝色位置上的数字重新排列。2.选择一个红色的把它改成蓝色。3.什么都不做。
输出获胜情况。
思路:
如果一个玩家要把序列排成有序,必须要把不正确的位置的数都改成蓝色,其他数改不改都无所谓,只要是蓝色的数就可以任意交换次序。问题转换成两个人谁先把自己需要改成蓝色的数选完。
对于一个玩家来说,他会选择一个位置不正确的且为红色的把它改为蓝色,如果存在一些位置是另外一个玩家也希望修改的,最优策略必然是尽量先避免选择这种公共的位置。因为这种位置可以等着另外一个玩家去修改,而非公共位置只能自己修改。
统计玩家1和玩家2需要修改的数目和公共修改的数目,按照这个策略模拟一遍即可。也可以推公式直接判断,但没必要。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include<bitset>
#include<list>
#include <algorithm>
#define pii pair<int,int>
#define pll pair<LL,LL>
#define pil pair<int,LL>
#define pli pair<LL,int>
#define pdd pair<db,db>
#define se second
#define fi first
#define endl '\n'
#define rep(i,a,b) for (register int i=a;i<b;++i)
#define per(i,a,b) for (register int i=a;i>b;--i)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define db double
#define eps 1e-9
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MOD=1e9+7;
const int N=5e5+10;
int a[N];
void solve()
{
int n,cnt1=0,cnt2=0,cnt=0;
cin>>n;
rep(i,1,n+1){
cin>>a[i];
if(a[i]!=i) ++cnt1;
if(a[i]!=n-i+1) ++cnt2;
if(a[i]!=i&&a[i]!=n-i+1) ++cnt;
}
for(int i=1;;++i){
if(cnt1==0&&cnt2==0){
cout<<"Tie"<<endl;
return;
}
if(cnt1==0){
cout<<"First"<<endl;
return;
}
if(cnt2==0){
cout<<"Second"<<endl;
return;
}
if(i&1){
if(cnt1>cnt) --cnt1;
else --cnt1,--cnt2,--cnt;
}else{
if(cnt2>cnt) --cnt2;
else --cnt1,--cnt2,--cnt;
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("title.in","r",stdin);
freopen("title.out","w",stdout);
#endif
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _=1;
cin>>_;
while(_--){
solve();
}
return 0;
}
F. Copy of a Copy of a Copy
题意:
一个n*m的0-1矩阵,每一次操作可以:1.选一个(x,y),它的上下左右都和它相反,且不为边界,可以把(x,y)改为相反的。2.复杂当前的图像。
给定k个复制出来的图和原图(顺序不确定),需要还原操作过程,确定原图是哪一个以及每一步复制的k是哪一个。
3≤n,m≤30; 0≤k≤100
思路:
如果对一个图进行了操作,这个图的合法操作数一定是减少的。统计所有图的合法操作个数,按照降序排列,第一个图作为原图,后面的图和前面一个做比较,不相同的坐标就是修改的坐标。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include<bitset>
#include<list>
#include <algorithm>
#define pii pair<int,int>
#define pll pair<LL,LL>
#define pil pair<int,LL>
#define pli pair<LL,int>
#define pdd pair<db,db>
#define pip pair<int,pii>
#define se second
#define fi first
#define endl '\n'
#define rep(i,a,b) for (register int i=a;i<b;++i)
#define per(i,a,b) for (register int i=a;i>b;--i)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define db double
#define eps 1e-9
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MOD=1e9+7;
const int N=35;
int n,m,k;
struct node{
string s[N];
int id,cnt;
}g[110];
int get_cnt(int u)
{
int res=0;
rep(i,2,n)
rep(j,2,m){
int x=g[u].s[i][j]-'0';
if(g[u].s[i+1][j]-'0'==1-x&&g[u].s[i-1][j]-'0'==1-x&&g[u].s[i][j-1]-'0'==1-x&&g[u].s[i][j+1]-'0'==1-x) ++res;
}
return res;
}
bool cmp(node a,node b)
{
return a.cnt>b.cnt;
}
void solve()
{
cin>>n>>m>>k;
rep(i,1,k+2){
g[i].id=i;
rep(j,1,n+1) cin>>g[i].s[j],g[i].s[j]='0'+g[i].s[j];
g[i].cnt=get_cnt(i);
}
sort(g+1,g+2+k,cmp);
cout<<g[1].id<<endl;
vector<pip>v;
rep(i,2,k+2){
if(g[i].cnt!=g[i-1].cnt) rep(j,1,n+1) rep(z,1,m+1) if(g[i-1].s[j][z]!=g[i].s[j][z]) v.push_back({1,{j,z}});
v.push_back({2,{g[i].id,0}});
}
cout<<v.size()<<endl;
for(auto it:v){
pii t=it.se;
if(it.fi==1) cout<<1<<" "<<t.fi<<" "<<t.se<<endl;
else cout<<2<<" "<<t.fi<<endl;
}
}
int main()
{
// #ifndef ONLINE_JUDGE
// freopen("title.in","r",stdin);
// freopen("title.out","w",stdout);
// #endif
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _=1;
//cin>>_;
while(_--){
solve();
}
return 0;
}
G. Gaining Rating
题意:
t(1≤t≤10^4)组测试,每组给定长度为n的数组a,初始分数x,求涨到y最小需要多少次比赛。每一次都可以选一个ai,如果当前分数大于等于ai就会加一分,否则减一分。但ai不会变,必须平均的选择,即不能存在一个人比另一个人多打两次比赛。
思路:
从小到大排序,每一轮次都从小的开始选,然后就变成一道模拟题了。
首先看一下当前轮最多能打败多少个对手,假如能打败前i-1个,第i个x<a[i]了,如果还没有到y,后面的会先掉分。判断一下之后每一次到i分数的净增量为2*(i-1)-n,如果为负值就不可能超过y了,否则计算经过多少轮之后x>=a[i],然后继续判断。注意y有小于a[i]的情况。
因为i指针只会向后移动,所以复杂度为O(n)。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include<bitset>
#include<list>
#include <algorithm>
#define pii pair<int,int>
#define pll pair<LL,LL>
#define pil pair<int,LL>
#define pli pair<LL,int>
#define pdd pair<db,db>
#define se second
#define fi first
#define endl '\n'
#define rep(i,a,b) for (register int i=a;i<b;++i)
#define per(i,a,b) for (register int i=a;i>b;--i)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define db double
#define eps 1e-9
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MOD=1e9+7;
const int N=2e5+10;
LL a[N];
void solve()
{
int n;
LL x,y;
cin>>n>>x>>y;
rep(i,1,n+1) cin>>a[i];
sort(a+1,a+n+1);
LL cnt=0;
int i=1;
while(1){
while(i<=n&&x>=a[i]){
++i,++x,++cnt;
if(x==y){
cout<<cnt<<endl;
return;
}
}
if(i==n+1){
cout<<cnt+y-x<<endl;
return;
}
if(n-i+1>=i-1){
cout<<-1<<endl;
return;
}
if(y<=a[i]){
LL len=2*(i-1)-n,d=y-x;
LL tm=d/len;
cnt+=tm*n;
if(d%len==0) cout<<cnt<<endl;
else cout<<cnt+d-tm*len+2*(n-i+1)<<endl;
return;
}
LL len=2*(i-1)-n,d=a[i]-x;
LL tm=d/len;
if(d%len) ++tm;
x+=tm*len,cnt+=n*tm;
if(x>=y){
cnt-=x-y;
cout<<cnt<<endl;
return;
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("title.in","r",stdin);
freopen("title.out","w",stdout);
#endif
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _=1;
cin>>_;
while(_--){
solve();
}
return 0;
}