武汉工程大学2020GPLT选拔赛(重现赛)(重现赛)

比赛链接

L1-7 拼接梯子

题解:通过举多个样例我们可以发现,凡是偶数并且前n项和大于m都存在答案,那么现在已知的所有满足该条件的数都存在满足题意的答案,于是便可以通过对答案的每一项除二,构造出最高项的答案(也就是右移m),最后强调int类型二进制最高位只有32位,而答案有64位(哭惨了,只拿到20分)详见代码。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
void solve() {
    int n,m;
    cin>>n>>m;
    int t=1;
    int an=0;
    for(int i=1;i<=n;i++){
        t*=2;
        an+=t;
    }
//     cout<<an<<endl;
    if (an < m || m &1)
        cout<<"No"<<endl;
    else {
        cout<<"Yes"<<endl;
        int ans = -1, cnt = 0;
        while (m) {
            if (m & 1)    ans = cnt;
            m >>= 1;
            ++cnt;
        }
        cout<<(1ll<<ans);
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int e=1;
//    cin>>t;
    while(e -- ){
        solve();
    }
    return 0;
}


L1-8 幻想乡炼金学

题解:写吧,模拟。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dd(x) cout << #x << " = " << x << "    "
#define de(x) cout << #x << " = " << x << endl
const ll mod = 1e9 + 7;
const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
ll gcd(ll a,ll b){return b ? gcd(b,a % b) : a;}
string s,ss,sss;
int main()
{
    getline(cin,s);
    for(int i = 0;i < s.size();++i){
        if(s[i] != ' '){
            ss += s[i];
        }
    }
    string tmp;
    int cnt = 0;
    for(int i = 0;i < ss.size();++i){
        if(ss[i] <= 'Z' && ss[i] >= 'A' && tmp.size()){
            sss += tmp;
            tmp = "";
            tmp += ss[i];
        }
        else if(ss[i] == '('){
            sss += tmp;
            tmp = "";
            while(ss[++i] != ')')
                tmp += ss[i];
            i++;
            cnt = 0;
            while(ss[i] != '}'){
                i++;
                if(ss[i] <= '9' && ss[i] >= '0'){
                    cnt = cnt * 10 + ss[i] - '0';
                }
            }
            string res = "";
            for(int j = 0;j < tmp.size();++j){
                if(tmp[j] >= 'A' && tmp[j] <= 'Z'){
                    res += tmp[j];j++;
                    while(j < tmp.size() && tmp[j] < 'A' || tmp[j] > 'Z'){
                        res += tmp[j];
                        ++j;
                    }
                    j--;
                }
                for(int k = 0;k < cnt;++k)
                    sss += res;
                res = "";
            }
            tmp = "";
        }
        else if(ss[i] == '{'){
            cnt = 0;
            while(ss[i] != '}'){
                i++;
                if(ss[i] <= '9' && ss[i] >= '0'){
                    cnt = cnt * 10 + ss[i] - '0';
                }
            }
            for(int j = 0;j < cnt;++j)
                sss += tmp;
            tmp = "";
        }
        else{
            tmp += ss[i];
        }
    }
    sss += tmp;
    cout << sss << endl;
    return 0;
}

L2-1 特殊的沉重球

题解:相当于枚举第i个物品放在哪个球里,一个简单的dfs就可以解决,要注意剪枝,回溯

代码:

#include <bits/stdc++.h>
using namespace std;
int n, m;
int w[30];
int sum[30];
int ans = 20;
void dfs(int u, int k)
{
    if (k >= ans)
        return;
    if (u == n)
        ans = k;
    for (int i = 0; i < k; i++)
        if (sum[i] + w[u] <= m)
        {
            sum[i] += w[u];
            dfs(u + 1, k);
            sum[i] -= w[u];
        }
    sum[k] = w[u];
    dfs(u + 1, k + 1);
    sum[k] = 0;
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> w[i];
    sort(w, w + n, greater<int>());
    dfs(0, 0);
    cout << ans << endl;
    return 0;
}

L2-2 又见火车入栈

题解:手写栈,模拟一下过程,对所有的查询排一个序,我卡过去的,即使开了输入输出流也过不了,最后改成scanf才过的

代码:


#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
// inline int read() {
//     int s = 0, w = 1; char ch = getchar();
//     while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
//     while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
//     return s * w;
// }
int n,w;
struct mp{
    int x,y,w;
    bool operator < (const mp& a)const {
        if (x == a.x)    return y < a.y;
        return x < a.x;
    }
}op[1000100];
int ans[1000100];
bool vis[1000100];
int kp[1000100];
void solve(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        char s[5];
        scanf("%s",s);
        if(s[0]=='i') vis[i+1]=1;
    }
    int m;
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
//         cout<<1<<endl;
        int l , r ;
        scanf("%d%d",&l,&r);
        op[i]={l,r,i};
        
    }
    sort(op+1,op+m+1);
    int k = 0, num = 0;
    int top=0;
    for (int i = 1; i <= m; ++i) {
        while (op[i].x != k) {
            if (vis[++k])    kp[++top] = ++num;
            else    --top;
        }
        ans[op[i].w] = kp[op[i].y];
    }

    for(int i=1;i<=m;i++){
        printf("%d\n", ans[i]);
    }
}
signed main(){
//     ios::sync_with_stdio(false);
//     cin.tie(0);
//     cout.tie(0);
    int t=1;
//    cin>>t;
    while(t--){
        solve();
    }
}

L2-3 新旷野地带

题解:组合数学题。首先选取kk行kk列,然后在这kk行kk列里面进行全排列。

代码:

#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
#define int long long
const int mod=1e9+7,N=1e6+5;
int n,m,k;
int in[N],f[N];
int qpow(int a,int p){
    int res=1;
    while(p){
        if(p&1) res=res*a%mod;
        a=a*a%mod;
        p>>=1;
    }
    return res;
}
int ans(int x,int y){
    if(x<y) return 0;
    return f[x]*in[y]%mod*in[x-y]%mod;
}
void solve(){
    cin>>n>>m>>k;
    f[0]=1;
    in[0]=1;
    f[1]=1;
    in[1]=1;
    for(int i=2;i<=N;i++){
        f[i]=f[i-1]*i%mod;
        in[i]=qpow(f[i],mod-2);
    }
    int res=0;
    for(int i=1;i<=min({k, n, m});i++){
        res=(res+ans(n,i)*ans(m,i)%mod*f[i])%mod;
    }
    cout<<res<<endl;

}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t=1;
//    cin>>t;
    while(t--){
        solve();
    }
}

L2-4 缘之空

题解:很经典的LCA问题,只需要找到父节点,然后套板子就行了

代码:

#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
int n,q;
vector<int>a[100010];
int dev[100010];
int f[100010][20];
int ff[100010];
void dfs(int u,int fa){
    dev[u]=dev[fa]+1;
    f[u][0]=fa;
    for(int i=1;i<=17;i++){
        f[u][i]=f[f[u][i-1]][i-1];
    }
    for(auto v:a[u]){
        if(v!=fa) dfs(v,u);
    }
}
int ans=0;
int lca(int x,int y){
    if(dev[x]<dev[y]) swap(x,y);
    for(int i=17;i>=0;i--){
        if(dev[f[x][i]]>=dev[y]) {
            x = f[x][i], ans += pow(2, i);
        }
    }
    if(x==y) return -1;
//    cout<<ans<<endl;
    for(int i=17;i>=0;i--){
        if(f[x][i]!=f[y][i])
            x=f[x][i],y=f[y][i],ans+=2*pow(2,i);
    }
//    cout<<f[x][0]<<" "<<f[y][0]<<endl;
    ans+=2;
    return ans+2;
}
void solve(){
    cin>>n>>q;
    for(int i=0;i<n-1;i++){
        int x,y;
        cin>>x>>y;
        ff[y]=x;
        a[x].push_back(y);
    }
    int fa=0;
    for(int i=1;i<=n;i++){
        if(ff[i]==0){
            fa=i;
            break;
        }
    }
    dfs(fa,0);
//    for(int i=1;i<=n;i++){
//        cout<<dev[i]<<endl;
//    }
//for(int i=0;i<n-1;i++){
//    for(int j=0;j<=15;j++){
//        cout<<f[i][j]<<" ";
//    }
//    cout<<endl;
//}
    while(q--){
        int x,y;
        cin>>x>>y;
        ans=0;
        int an=lca(x,y);
        if(ans>=5&&an!=-1)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
        cout<<ans<<endl;
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t=1;
//    cin>>t;
    while(t--){
        solve();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值