2020 ICPC 上海赛区

赛时6题。第七题我写的没de出来(给队友跪了)
xixike哥太强了有5题代码都是他写的(我只写了半题)
ggxxdd哥也非常强特别会数学题。
只有我什么都不会

G,B

都是队友切的签到,没看

M:

虽然会有重复的,但只要把前缀一起放到map里去就不会有任何重复的点因此可以打标记,这样就能建树了。然后就是dfs如果子树全被删除了该父节点就可以删除,否则就只能挨个删子节点。
我写了建树的部分,队友写的dfs

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int N = 1e5 + 10;
string s[105];
vector<int>E[10005];
int k;
bool vis[10005];
map<string,int>mp;
int ans=0;
int siz[N], num[N];

void dfs(int x){
    // cout << "dfs " << x << endl;
    if(vis[x]) num[x] = 1;
    if(!E[x].size()) siz[x] = 1;
    for(auto y : E[x]){
        dfs(y);
        siz[x] += siz[y], num[x] += num[y];
    }    
    return;
}

inline void get_ans(int x){
    // cout << "x " << x << " " << num[x] << " " << siz[x] << endl;
    if(x > 1 && num[x] == siz[x]) return ans++, void();
    for(auto y : E[x]) get_ans(y);
}

void solve(){
    mp.clear();k=0,ans=0;
    int n,m;cin>>n>>m;
    for(int i = 1; i <= n + m; ++i) cin >> s[i];
    // sort(s + 1, s + 1 + n + m);
    // for(int i=1;i<=n;i++)cin>>s[i];
    // for(int j=1;j<=m;j++)cin>>s[j+n];
    mp["0"] = ++k;
    for(int i=1;i<=n+m;i++){
        string tmp="",s1="0";
        for(int j=0;j<=(int)s[i].size();j++){
            if(s[i][j]=='/'||j==s[i].size()){
                string s2=s1;
                if(!mp[s1]) mp[s1] = ++k;
                s1 = s1 + '/' + tmp;
                tmp="";
                if(mp[s1] && mp[s2]) continue;
                if(!mp[s1]) mp[s1]=++k;
                // cout<<s1<<"\n";
                E[mp[s2]].push_back(mp[s1]);
                // cout << "add " << i << " " << j << "  " << s2 << "   " << s1 << endl;
                if(j==s[i].size()&&i<=n)vis[mp[s1]]=1;
            }
            else{
                tmp+=s[i][j];
            }
        }
    }
    dfs(1), get_ans(1);
    cout<<ans<<"\n";
    for(int i=1;i<=k;i++)E[i].clear(),vis[i]= num[i] = siz[i] = 0;
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    int tt;cin>>tt;while(tt--){
        solve();
    }
}

D:

二分题。但是wa6,因为少考虑了第三种情况。。。

I:

考虑出在一个圆上应该如何走即可解决。

C:

据队友说是数位dp加上一些别的但是总之我不会

H:

赛时写完了没de完。思路队友切的。分为两段。
1.观察到把人和菜分别连线不会出现交叉的情况,所以可以枚举匹配
2.桌子最多只会调换一次方向

#include <bits/stdc++.h>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1e3 + 500;
int n, k, a[N], b[N],p2[N],p1[N];

int disr(int x,int y){
	return (x-y+n)%n;
}
int disl(int x,int y){
	return (y-x+n)%n;
}
bool cmp1(const int &x, const int &y) {
	return disl(a[x],b[p1[x]])<disl(a[y],b[p1[y]]);
}
bool cmp2(int x,int y){
	return disr(a[x],b[p1[x]])<disr(a[y],b[p1[y]]);
}
void solve() {
    cin >> n >> k;
    for (int i = 0; i < k; i++)cin >> a[i];
    for (int i = 0; i < k; i++)cin >> b[i];
    sort(a , a  + k);
    sort(b , b  + k);
    int ans=0x3f3f3f3f;
    for(int j=0;j<k;j++)p2[j]=j;
    for(int i=0;i<k;i++){
    	for(int j=0;j<k;j++){
    		p1[j]=(i+j)%k;
		}
		//left
		sort(p2,p2+k,cmp1);
		ans=min(ans,disl(a[p2[k-1]],b[p1[p2[k-1]]]));
		int mx=0;
		for(int j=k-2;j>=0;j--){
			int pos=disl(a[p2[j]],b[p1[p2[j]]]);
			mx=max(mx,disr(a[p2[j+1]],b[p1[p2[j+1]]]));
			ans=min(ans,mx+pos*2);
		}
		//right
		sort(p2,p2+k,cmp2);
		ans=min(ans,disr(a[p2[k-1]],b[p1[p2[k-1]]]));
		mx=0;
		for(int j=k-2;j>=0;j--){
			int pos=disr(a[p2[j]],b[p1[p2[j]]]);
			mx=max(mx,disl(a[p2[j+1]],b[p1[p2[j+1]]]));
			ans=min(ans,mx+pos*2);
		}
	}
	cout<<ans<<endl;
}

int main() {
    int t;
    cin >> t;
    for (int i = 1; i <= t; i++) {
        solve();
    }
}

E:

dp递推,每次最小的数必须放在前k个
如果能观察出1应该如何放的话其实不难想到怎么dp。。
式子需要稍微推一下就可以O(n)

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e7+10,mod=998244353;
int dp[maxn],inv[maxn];
void solve() {
    int n,k;cin>>n>>k;
    inv[0]=1;inv[1]=1;
    for(int i=2;i<=n;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    int sum=1;
    dp[0]=1;
    for(int i=1;i<=n;i++){
    	dp[i]=sum*inv[i]%mod;
    	sum=(sum+dp[i])%mod;
    	if(i>=k)sum=(sum+mod-dp[i-k])%mod;
	}
	for(int i=2;i<=n;i++)dp[n]=dp[n]*i%mod;
	cout<<dp[n]<<endl;
}

signed main() {
    int t=1;
    //cin >> t;
    for (int i = 1; i <= t; i++) {
        solve();
    }
}

L:

其他题过的人没上百就不补了,收工

posted @ 2024-09-16 21:05  lyrrr  阅读(31)  评论(0)    收藏  举报