icpc2023西安邀请赛部分题解(GJAHE)

题目链接:The 2023 ICPC Xi'an Invitational Programming Contest - 比赛主页 - 比赛 - QOJ.ac

G. Permutation

思路

纯签到没啥好说的

代码

void solve(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cout<<i<<" ";
    }
}

J. Target

思路

可以对a进行的操作:1.a/2 2.a/2+0.5 对于0<=a<=1我们发现操作1能让a变小,操作2能让a变大

我们可以尝试先把a变成0,再把a变成b,暴力打表发现第一步最大不会超过15,第二步不会超过20,直接暴力搜索即可

代码

#include<bits/stdc++.h>
using namespace std;

#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;

const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;
const double eps=1e-4;

void solve(){
    vector<int> ans;
    double a,b;
    cin>>a>>b;
    while(a>eps){
        a/=2;
        ans.push_back(1);
    }
    vector<int> t(50,0);
    bool f=false;
    auto dfs=[&](auto self,double x,int ct)->void{

        if(f||ct>20) return;
        if(abs(x-b)<=eps){
            for(int i=0;i<ct;i++){
                cout<<t[i];
            }
            f=true;
            return;
        }
        t[ct]=1;
        self(self,(x*1.0)/2,ct+1);
        t[ct]=2;
        self(self,(x*1.0)/2+0.5,ct+1);

    };
    for(int i:ans){
        cout<<i;
    }
    dfs(dfs,0,0);
    
}
signed main() {
    vcoistnt
    cout<<fixed<<setprecision(2);
    int _=1;
    // cin>>_;
    while(_--) solve();
    return 0;
}

A. Alice and Bob

思路

此题思路模拟样例就能得出

当以p[1]为开头的时候,p[1]长度内p[1]后面的数必须大于p[1]才能使得Bob获胜

那么这题就变成了组合数学的问题,

将所有开头的情况枚举,答案相加即可

代码

#include<bits/stdc++.h>
using namespace std;

#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;

const int N=1e7+10;
const int inf=1e18;
const int mod=998244353;


int fac[N];
int inv[N];

int ksm(int a,int b){
    int ans=1;
    while(b){
        if(b&1){
            ans=(ans*a)%mod;
        }
        a=((a%mod)*(a%mod))%mod;
        b>>=1;
    }
    return ans;
}

int C(int n,int m){
    if(m>n) return 0;
    return fac[n] * inv[m]%mod * inv[n-m]%mod;
}

void init(){
    fac[0]=1;
    inv[0]=1;
    for(int i=1;i<N;i++){
        fac[i]=(fac[i-1]*i)%mod;
    }
    inv[N-1]=ksm(fac[N-1],mod-2);
    for(int i=N-2;i>=1;i--){
        inv[i]=inv[i+1]*(i+1)%mod;
    }
}

int A(int n,int m){
    if(m>n || m<0 || n<0){
        return 0;
    }
    return fac[n]*inv[n-m]%mod;
}

void solve(){
    int n;cin>>n;
    int ans=0;
    
    for(int i=1;i<=n;i++){
        ans=(ans+A(n-i,i-1)*A(n-i,n-i))%mod;
    }

    cout<<ans<<"\n";
}
signed main() {
    vcoistnt
    cout<<fixed<<setprecision(2);
    int _=1;
    init();
    // cin>>_;
    while(_--) solve();
    return 0;
}

H. Spin the Wheel

思路

严格证明不是很会,只能说这题做出来全凭经验找规律猜结论,多观察几个例子我们发现,当我们在旋转之后加我们不会影响相邻两数之间差值%n的相等性,如果差值%n不相等直接输出-1

但相邻两数之间的差值%n是可以改变的,我们发现我们每进行一次操作便能使差值+1,然后我们贪心的求最小值,那么答案便是差值%n,如果a[0]!=0便需要再操作1次

特殊如果所有值都相等时特判一下

代码

#include<bits/stdc++.h>
using namespace std;

#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;

const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;

void solve(){
    int n;
    cin>>n;
    vi a(n+10);
    int isame=0;
    bool f=false;
    for(int i=0;i<n;i++){
        cin>>a[i];

        if(i==0) isame=a[i];
        else{
            if(a[i]!=isame) f=true;
        }

    }
    if(!f){
        if(isame==0) cout<<"0\n";
        else cout<<n+1<<"\n";
        return;
    }
    int x=(a[1]-a[0]+n)%n;

    int ans=x+(a[0]!=0);
    for(int i=0;i<n;i++){
        if( (a[(i+1)%n] - a[i%n]+n) %n != x) ans=-1;
    }
    cout<<ans<<"\n";

}
signed main() {
    vcoistnt
    cout<<fixed<<setprecision(2);
    int _=1;
    // cin>>_;
    while(_--) solve();
    return 0;
}

E. Merge the Rectangles

思路

刚开始的思路便是我们遇到一条能合并的边便将其合并,之后发现这并不可行

观察例子我们发现对于一个合法的图像,即如果一个矩形最终能合并的话那么这个矩形内部必然存在至少一条能够贯穿此矩形的线,这条线能够将此矩形分为两个小矩形

那么我们递归暴力搜索一下就行,因为是01那么我们可以用前缀和来判断这条线是否贯穿

代码

#include<bits/stdc++.h>
using namespace std;

#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;

const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;

vector<vi> x(1505,vi(1505));
vector<vi> y(1505,vi(1505));

bool dfs(int x1,int y1,int x2,int y2){
    int sum=0;
    for(int i=x1+1;i<x2;i++){
        if(y[i][y2-1]-y[i][y1-1]==y2-y1){
            return dfs(x1,y1,i,y2) && dfs(i,y1,x2,y2);
        }
        sum+=y[i][y2-1]-y[i][y1-1];
    }
    for(int i=y1+1;i<y2;i++){
        if(x[x2-1][i]-x[x1-1][i]==x2-x1){
            return dfs(x1,y1,x2,i)&&dfs(x1,i,x2,y2);
        }
        sum+=x[x2-1][i]-x[x1-1][i];
    }
    if(!sum) return true;
    return false;
}


void solve(){
    int n,m;
    cin>>n>>m;
    for(int i=2;i<=n;i++){
        for(int j=1;j<=m;j++){
            char c;cin>>c;
            y[i][j]+=(c-'0');
            y[i][j]+=y[i][j-1];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=2;j<=m;j++){
            char c;cin>>c;
            x[i][j]+=(c-'0');
            x[i][j]+=x[i-1][j];
        }
    }
    if(dfs(1,1,n+1,m+1)) cout<<"YES\n";
    else cout<<"NO\n";
}
signed main() {
    vcoistnt
    cout<<fixed<<setprecision(2);
    int _=1;
    // cin>>_;
    while(_--) solve();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值