A. Strange Functions
题意:定义f()函数为把放进去的数倒置,并去掉前导零。 g ( x ) = x f ( f ( x ) ) g(x)=\frac{x}{f(f(x))} g(x)=f(f(x))x,给定n。在所有 1<= x <= n中,能使得g(x)取得几个不同的值。
思路:f(x)套了两层,先倒置去掉了前导零,又倒置去掉了前导零。其实就是倒回来了。然后用x去除它。假设x后面没有0。那么g(x)就是1。如果有一个0,那就是10。以此类推。所以答案就是n的位数。想必找规律也能看出来。
AC代码:
#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int ans[N];
signed main(){
cin>>t;
while(t--){
string s;
cin>>s;
cout<<s.size()<<endl;
}
}
B. Jumps
题意:初始在0点。要跳到x点(x > 0)。在第i次跳跃中。要么跳到 y+i的位置,要么跳到y-1的位置。求到x,最少跳多少步。
思路:先考虑最简单的情况。就是先一直往右跳。跳过头了,再慢慢跳回来。这样就可以求出。至少要往右跳x次。然后可以发现。如果跳过头了,是比较亏的。因为可能要花很多步再跳回来。那怎么避免跳过头呢。就是提前往回跳。从而避免一次往右跳。这样就相当于少往右走了i-1步。枚举这个i。看看有没有可行解就行了。
AC代码:
#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int ans[N];
int sel = 0;
signed main(){
cin>>t;
while(t--){
cin>>n;
int now = 0;
int res = 0;
int last = 0;
for(int i = 1 ; now < n ; i ++){
now += i;
res ++;
last = i;
}
res += now-n;
int tmp = now-n;
for(int i = 1 ; i <= last ; i ++){
if(now-i-1 == n){
res = min(res,res-tmp);
}
}
cout<<res<<endl;
}
}
C. Ping-pong
题意:两个人打乒乓球。分别有x,y次击球机会。发球也算。有击球机会100%能打回去。 没机会100%打不回去。但是可以选择不打。保留次数。在保证能让自己多赢对手少赢的情况下。求每个人最多可以赢多少局。
思路:很容易想到。先手发球时很亏的。因为要赢的话,得浪费两次机会。而后手可以用一次机会获胜。如果对手机会没了。那直接发球就赢了。所以贪心策略就出来了。 如果对手还有机会,并且它发球。那我不接。让他赢。如果他是最后一次机会了。那我打回去。 我就赢一局了。剩下的我随便打。对面没机会了我全赢。所以后手y次机会就能赢y次。先手赢x-1次。
AC代码:
#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int ans[N];
int sel = 0;
map<int,int> mp;
struct node{
int x,w;
node(int a,int b):x(a),w(b){}
};
queue<node> que;
signed main(){
cin>>t;
while(t--){
int x,y;
cin>>x>>y;
int res1 = 0;
int res2 = 0;
res1 = x-1;
res2 = y;
cout<<res1<<" "<<res2<<endl;
}
D. Sequence and Swaps
题意:给定一个数组和一个x。然后每次可以选择一个比x大的数,swap(a[i],x),然后重复这个操作。直到数组有序。
思路:首先,这样连续的交换,一定是发生在一个递增子序列上的。因为x在不断的变大。那么这个子序列的起点就很重要了。枚举一个起点。然后碰到比x大的就交换。因为如果碰到比x大的而不交换的话。必须保证后面都是有序的,如果后面还有不是有序的。那么这次不交换。之后就更不能换了。肯定时无序的。
AC代码:
#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int ans[N];
bool check(int n){
for(int i = 1 ; i <= n ; i ++){
if(b[i] < b[i-1]) return false;
}
return true;
}
int cal(int pos){
int now = b[pos];
b[pos] = m;
int cnt = 1;
for(int i = pos ; i <= n ; i ++){
if(check(n)) return cnt;
if(b[i] > now){
swap(b[i],now);
cnt ++;
}
}
if(!check(n)) return -1;
return cnt;
}
signed main(){
cin>>t;
while(t--){
cin>>n>>m;
for(int i = 1 ; i <= n ; i ++) cin>>a[i],b[i] = a[i];
a[0] = 0; a[n+1] = 1e9;
int res = 1e18;
if(check(n)) res = 0;
for(int i = 1 ; i <= n ; i ++){
if(a[i] <= m) continue;
for(int j = 1 ; j <= n ; j ++)
b[j] = a[j];
int tmp = cal(i);
if(tmp != -1){
res = min(res,tmp);
}
}
if(res < 1e18){
cout<<res<<endl;
}else{
cout<<-1<<endl;
}
}
}
/**
**/
E. Four Points
题意:给四个点。移动他们,使得形成一个正方形。 求最小移动步数。
思路参考:https://www.cnblogs.com/qieqiemin/p/14069636.html
思路: x和y可以分开考虑。 首先枚举每个点作为四个点的任意一个点。也就是枚举所有排列。然后再进行计算。单独考虑x。设左下,右下,左上,右上,分别为 p0,p1,p2,p3。然后对于 p0-p2,可以求出一个x的范围 x1-x2。就是min(p0.x,p2.x) - max(p0.x,p2.x) 。同理对于 p1-p3 一样求。然后就会得出两个区间。 如果左边小于右边。那就让他们移动到各自的中点去就行了。这样移动距离是最小的。如果右边 小于左边。那就全部移动到min(p0.x,p2.x)就好了。边长为0也是合法的。对于y轴。是一样考虑的。这时候。得到了一个 水平的边长范围。和一个竖直的边长范围。如果 横着和竖着有交集。那就直接是 costx+costy。就是总的cost。如果没有交集。那必然需要两个点做出让步。移动到边长相等的地方去。这就加上额外的cost就行了。
AC代码:
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
using namespace std;
const int N = 1e6+7;
const int mod = 1e9+7;
int t = 1,n,m,k;
struct node{
int x,y;
}p[N];
int sum[N];
set<pair<int,int> > st;
signed main(){
cin>>t;
while(t-- ){
int b[] = {0,1,2,3};
for(int i = 0 ; i < 4 ; i ++){
cin>>p[i].x>>p[i].y;
}
int res = 1e18;
do{
int x1 = min(p[b[0]].x,p[b[2]].x);
int x2 = max(p[b[0]].x,p[b[2]].x);
int x3 = min(p[b[1]].x,p[b[3]].x);
int x4 = max(p[b[1]].x,p[b[3]].x);
int y1 = min(p[b[0]].y,p[b[1]].y);
int y2 = max(p[b[0]].y,p[b[1]].y);
int y3 = min(p[b[2]].y,p[b[3]].y);
int y4 = max(p[b[2]].y,p[b[3]].y);
int costx,costy;
int x_l,x_r,y_l,y_r;
if (x4 < x1) {
x_l = x_r = 0;
costx = x2 - x3 + x1 - x4;
} else {
x_l = max(x3 - x2, 0ll);
x_r = x4 - x1;
costx = x2 - x1 + x4 - x3;
}
if (y4 < y1) {
y_l = y_r = 0;
costy = y2 - y3 + y1 - y4;
} else {
y_l = max(y3 - y2, 0ll);
y_r = y4 - y1;
costy = y2 - y1 + y4 - y3;
}
int cost = costx + costy;
if (y_l > x_r) {
cost += (y_l - x_r) << 1;
} else if (x_l > y_r) {
cost += (x_l - y_r) << 1;
}
res = min(res, cost);
}while(next_permutation(b,b+4));
cout<<res<<endl;
}
return 0;
}