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:
其他题过的人没上百就不补了,收工
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步