2019-2020 ICPC Asia Hong Kong Regional Contest 补题(部分)

codeforces原题连接
大佬题解html

B - Binary Tree

每一个人每次必定拿走奇数( 2 k − 1 2^k-1 2k1)个节点,若是先手必胜不难发现两人轮流拿最终必定拿奇数次(每次奇数个节点)说明一共有奇数个节点,若是先手必败说明最终两人共拿偶数次说明有偶数个节点,所以能够根据奇偶性判断输赢。ios

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=50010;
const ll mod=998244353;
int n;
int main()
{ 
 
  
    IO;
    int T=1;
    cin>>T;
    while(T--)
    { 
 
  
        cin>>n;
        for(int i=1;i<n;i++)
        { 
 
  
            int a,b;
            cin>>a>>b;
        }
        if(n&1) cout<<"Alice\n";
        else cout<<"Bob\n";
    }
    
    return 0;
    
}

D - Defining Labels

模拟一下就便可。web

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=50010;
const ll mod=998244353;
int main()
{ 
 
  
    IO;
    int T=1;
    cin>>T;
    while(T--)
    { 
 
  
        int k;ll x;
        cin>>k>>x;
        ll base=1,s=0;
        while(s<x)
        { 
 
  
            base=base*k;
            s+=base;
        }
        
        x-=s-base;
        base/=k;
        vector<int> ans;
        while(x>0&&base)
        { 
 
  
            
            int r=(x+base-1)/base;
            ans.push_back(r+9-k);
            x-=(r-1)*base;   
            base/=k;
        }
        for(auto t:ans) cout<<t;
        cout<<'\n';
        
    }
    
    return 0;
    
}

G - Game Design

原本想着构造一条链,不过发现 k k k有点大搞不了,因而。。就没有因而了
参考上述题解发现本身仍是对递归不熟练。数组

若是当前节点的方案数为偶数,那么咱们构造两个方案数分别为 2 , n 2 2,\frac n 2 2,2n 的子节点;若是是奇数就构造两个方案数分别为
2 , n 2 2,\frac n 2 2,2n 的子节点,而且根节点单独做为一种方案,递归终点是 k ≤ 2 k≤2 k2 的时候,咱们只须要建一条链便可。markdown

当父节点的权值等于孩子节点的权值和的时候,父节点便可单独称为一种方案,若是大于就不能单独称为一种方案。svg

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=50010;
const ll mod=998244353;
int k,cnt;
int fa[N],c[N];
int dfs(int k,int p)
{ 
 
  
    int now=++cnt;
    fa[now]=p;
    if(k<=2)
    { 
 
  
        fa[++cnt]=now;
        c[cnt]=1;
        c[now]=3-k;
        return 1;
    }
    c[now]=dfs(k/2,now)+dfs(2,now)+(k%2==0);
    return c[now]-(k%2==0);
    
}
int main()
{ 
 
  
    IO;
    int T=1;
    //cin>>T;
    while(T--)
    { 
 
  
        cin>>k;
        dfs(k,0);
        cout<<cnt<<'\n';
        for(int i=2;i<=cnt;i++) cout<<fa[i]<<' ';
        cout<<'\n';
        for(int i=1;i<=cnt;i++) cout<<c[i]<<' ';
        cout<<'\n';
    }
    
    return 0;
    
}

E - Erasing Numbers

大佬题解
直接贴贴大佬题解的图片吧真的很是妙
在这里插入图片描述spa

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=5010;
const ll mod=998244353;
int a[N],n;
bool check(int x)
{ 
 
  
    int cnt0=0,cnt1=0;
    for(int i=1;i<=n;i++) cnt0+=a[i]<x,cnt1+=a[i]>x;

    if(cnt0==cnt1) return 1;
    else if(cnt0<cnt1)
    { 
 
  
        int cnt=0;
        for(int i=1;i<=n;i++)
        { 
 
  
            if(a[i]>x) cnt++;
            else if(a[i]==x) cnt=0;//最后消x
            else cnt=max(cnt-1,0);
            if(cnt==3)
            { 
 
  
                cnt1-=2,cnt=1;
                if(cnt0==cnt1) return 1;
            }
        }
    }
    else 
    { 
 
  
        int cnt=0;
        for(int i=1;i<=n;i++)
        { 
 
  
            if(a[i]<x) cnt++;
            else if(a[i]==x) cnt=0;//最后消x
            else cnt=max(cnt-1,0);
            if(cnt==3) 
            { 
 
  
                cnt0-=2,cnt=1;
                if(cnt0==cnt1) return 1;
            }
        }
    }
    return 0;
    
}
int main()
{ 
 
  
    IO;
    int T=1;
    cin>>T;
    while(T--)
    { 
 
  
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=n;i++)
        { 
 
  
            if(check(a[i])) cout<<1;
            else cout<<0;
        }
        cout<<'\n';
    }
    
    return 0;
    
}

J - Junior Mathematician

居然还有点卡常,少了几个%就A了。
为了补这个题重学数位dp,而后发现基本的数位dpcode

// 2652 ms
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=5010;
const ll mod=1e9+7;
int a[N];
char l[N],r[N];
int m;
int f[N][65][65][2];
int ten[N];
int dfs(int pos,int s,int cur,bool limit)
{ 
 
  
    if(!pos) return cur==0;
    if(f[pos][s][cur][limit]!=-1) return f[pos][s][cur][limit];
    int v=limit?a[pos]:9;
    ll res=0;
    for(int i=0;i<=v;i++)
        res+=dfs(pos-1,(s+i)%m,((cur+s*i-i*ten[pos-1])%m+m)%m,limit&&i==v);
    
    res=(res%mod+mod)%mod;
    return f[pos][s][cur][limit]=res;
}
int solve(char s[])
{ 
 
  
    
    int cnt=strlen(s);
    // 初始化记忆化数组
    for(int i=1;i<=cnt;i++)
        for(int j=0;j<m;j++)
            for(int k=0;k<m;k++)
                f[i][j][k][0]=f[i][j][k][1]=-1;
                
    for(int i=1;i<=cnt;i++) a[i]=s[cnt-i]-'0';
  
    return dfs(cnt,0,0,1);
}
int main()
{ 
 
  
    IO;
    int T=1;
    cin>>T;
    
    while(T--)
    { 
 
  
        cin>>l+1>>r+1;
        cin>>m;
        ten[0]=1;
        for(int i=1;i<=5000;i++) ten[i]=ten[i-1]*10%m;
        // [l,r] 差分-> [0,r]-[0,l-1] 首先让l-1
        for(int i=strlen(l+1);i;i--)
        { 
 
  
            if(l[i]>'0') 
            { 
 
  
                l[i]--;
                break;
            }
            else l[i]='9';
        }
        cout<<((solve(r+1)-solve(l+1))%mod+mod)%mod<<'\n';
    }
    return 0;
    
}

最近做业巨难,信号+数电,感受老师上课疯狂划水,真就自学???
并且最近题解质量真的差,没时间打markdown不想打
要加油哦~xml