Codeforces Round #822 (Div. 2) 题解

Codeforces Round #822 (Div. 2) 题解,第1张

A. Select Three Sticks

题意为每一次可以选一个数加1或减1,问达到数组中有三个相等的数的最小步数

签到题,可能会有很多种解法

这里说其中一种

我们把整个数组排序,然后对于每一个三元组,把紧邻他的前后元素改成此元素,更新答案即可

代码如下

#include 
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et  cout<<'\n'
#define x first
#define y second
using namespace std;
template void input(_Tp &x){
    char ch(getchar());bool f(false);while(!isdigit(ch))f|=ch==45,ch=getchar();
    x=ch&15,ch=getchar();while(isdigit(ch))x=x*10+(ch&15),ch=getchar();
    if(f)x=-x;
}
template void input(_Tp &t,Args &...args){input(t);input(args...);}
const int N=1e6+10;
int a[N];
signed main(){
    int T;
    cin>>T;
    while(T--){
        int n;
        cin>>n;
        fer(i,1,n){
            fer(j,1,i){
                if(j==1 || j==i){
                    cout<<1<<" ";
                }
                else{
                    cout<<0<<" ";
                }
            }
            cout<<'\n';
        }
    }
	
}
 B. Bright, Nice, Brilliant 

这个题意真的是晦涩难懂

意思就是,每个房间可以通向和

每个房间的亮度等于 他自己的是否亮+与多少个亮的房间可以到达他

就比如这个图吧,我们拿举例,因为他自带一个亮度,而可以到达他并且亮的房间是

,所以他的亮度是4

而题意让我们输出一个,每一层所有房间亮度都相等的金字塔

其实第三个样例已经提示答案了,我们只需要让两边是亮的即可,大家看这张图

 假设我们验证一下最底层的11-15号点,对于11号点,他的亮度为5(1,2,4,7,11)

而每向右移动一格,左边会减少一个亮度(11),右边就会增加一个亮度(3)

每一格都是这样,也就保证了每一层所有格子亮度相同

 代码如下

const int N=1e6+10;
int a[N];
signed main(){
    int T;
    cin>>T;
    while(T--){
        int n;
        cin>>n;
        fer(i,1,n){
            cin>>a[i];
        }
        sort(a+1,a+1+n);
        int res=1e9+7;
        fer(i,2,n-1){
            res=min(res,abs(a[i]-a[i-1])+abs(a[i+1]-a[i]));
        }
        cout<
C. Removing Smallest Multiples

题意大概意思是,给我们一个要删的集合,1e6以内

选一个数K,你可以删掉集合中最小K的倍数,花费为K

首先我们知道暴力是一定不可以的,因为判断每一个数最差都要On,n方就爆了

我们可以换一个思路来枚举K,之后枚举K的倍数(这个过程是logn)

如果命中,就把K用掉

整体复杂度是n*logn,可以过

代码如下

#include 
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et  cout<<'\n'
#define x first
#define y second
using namespace std;
template void input(_Tp &x){
    char ch(getchar());bool f(false);while(!isdigit(ch))f|=ch==45,ch=getchar();
    x=ch&15,ch=getchar();while(isdigit(ch))x=x*10+(ch&15),ch=getchar();
    if(f)x=-x;
}
template void input(_Tp &t,Args &...args){input(t);input(args...);}
const int N=1e6+10;
int a[N];
int st[N];
string s;
int n;
signed main(){
    int T;
    input(T);
    while(T--){
        input(n);
        cin>>s;
        s='0'+s;
        fer(i,0,n) st[i]=0;
        int res=0;
        fer(i,1,n){
            for(int j=i;j<=n;j+=i){
                if(s[j]=='1') break;
                if(st[j]){
                    continue;
                }
                if(s[j]=='0' && !st[j]){
                    res=res+i;
                    st[j]=1;
                }
            }
        }
        printf("%lld\n",res);
 
    }
	
}
D. Slime Escape

题意大概为,给一个数组a,现在在k位置,可以左右吃但不能吃成负数,问可不可以走到0或n+1,也就是走出这个数组的一边

这道题一样非常多的解法,有一边扩张另一边队列的,有双指针两边扩张的等等

但无一例外就是 难写!

大家可以去翻一下cf的榜,找一个自己好理解的写法

这里介绍一种写法

大致思路就是先向一边走,把另一边用队列存起来

如果走不通了,就用走过去经过的最大值向另一边扩张

再用另一边的最大值向原方向扩张

之后两个方向进行两次

需要记录沿途吸收的能力,目前能量

这题是真的恶习

#include 
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et  cout<<'\n'
#define x first
#define y second
using namespace std;
template void input(_Tp &x){
    char ch(getchar());bool f(false);while(!isdigit(ch))f|=ch==45,ch=getchar();
    x=ch&15,ch=getchar();while(isdigit(ch))x=x*10+(ch&15),ch=getchar();
    if(f)x=-x;
}
template void input(_Tp &t,Args &...args){input(t);input(args...);}
const int N=1e6+10;
int a[N];
int n,k;
int qz[N];
bool check(int t){
    fer(i,1,n){
        qz[i]=qz[i-1]+a[i];
    }
    queue q;
    der(i,t-1,1){
        q.push(a[i]);
    }
    int now=a[t];
    int v=now;
    int id=t;
    fer(i,t+1,n){
        if(now+a[i]>=0){
            now+=a[i];
            if(now-v>=0){
                v=now;
                id=i;
            }
        }
        else{
            while(q.size()!=0){
                if(q.size()&&q.size()==1){
                    auto t=q.front();
                    if(v+t>=0) return true;
                }
                int t=q.front();
                if(v+t>=0){
                    v+=t;
                    now+=t;
                    q.pop();
                    if(v+qz[i]-qz[id]>=0){
                        now+=a[i];
                        if(now>=v){
                            id=i;
                            v=now;
                        }
                        break;
                    }
                }
                else{
                    return false;
                }
            }
        }
    }
    return true;
}
signed main(){
    int T;
    input(T);
    fer(kk,1,T){
        input(n,k);
        fer(i,1,n){
            input(a[i]);
        }
        bool fl=0;
        if(check(k)){
            fl=1;
        }
        reverse(a+1,a+1+n);
        if(check(n-k+1)){
            fl=1;
        }
        if(fl==1){
            cout<<"YES"<<'\n';
        }
        else{
            cout<<"NO"<<'\n';
        }
    }
	
}
E. Rectangular Congruence

题意:要求构造一个n*n的矩阵,满足以下条件

保证n为素数

这是个半结论题

我们把第二个条件移项

mod n

因此我们只需要让每一行为公差不同的等差数列即可 公差在0-n-1

而结合第一个条件,我们要让

即可

代码如下:

#include 
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et  cout<<'\n'
#define x first
#define y second
using namespace std;
template void input(_Tp &x){
    char ch(getchar());bool f(false);while(!isdigit(ch))f|=ch==45,ch=getchar();
    x=ch&15,ch=getchar();while(isdigit(ch))x=x*10+(ch&15),ch=getchar();
    if(f)x=-x;
}
template void input(_Tp &t,Args &...args){input(t);input(args...);}
const int N=1e6+10;

signed main(){
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        int b;
        cin >> b;
        for (int j = 0; j < n; j++) {
        cout << (i * (j - i + n) + b) % n << " ";
        }
        cout << "\n";
    }
}

 这场感觉总体体验真的不是很好,,尤其是那个D

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/3002708.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-27
下一篇 2022-09-27

发表评论

登录后才能评论

评论列表(0条)