2023年多校联训NOIP层测试2
2023年多校联训NOIP层测试2
爆零了
T1 HDU 4786 Fibonacci Tree \(0pts\)
@wangyunbiao: 不可以,总司令
我:不,可以,总司令
@wangyunbiao: 我 \(T1\) 爆零了
我: 我 \(T1\) 也爆零了
- 赛场上初读题面,以为是毒瘤数据结构(被题面背景祸害),然后直接就跳了(祭)。
- 易知,令在题目中所给的图的最大生成树的边权之和为 \(maxx\) ,最小生成树的边权之和为 \(minn\) ,那么在 \(minn\) ~ \(maxx\) 之间存在一个数是斐波那契数,则存在一种构造方式使得构造出一棵斐波那契树(因为原图的边权只有 \(0\) 和 \(1\))。
- 预处理 \(Fibonacci\) ,再跑最小生成树和最大生成树即可(我跑的是 \(Kruskal\) )。
- 本题常数有点大,请使用 \(scanf,printf\) 或关闭 \(cin,cout\) 同步流 。
#include<bits/stdc++.h> using namespace std; #define ll long long #define sort stable_sort #define endl '\n' struct node { int u,v,w; }e[300000]; int f1[300000],f2[300000],fib[300000],vis[300000],cnt,minn,maxx; void add(int u,int v,int w) { cnt++; e[cnt].u=u; e[cnt].v=v; e[cnt].w=w; } bool cmp(node a,node b) { return a.w<b.w; } int find(int x,int f[]) { if(f[x]==x) { return f[x]; } else { return f[x]=find(f[x],f); } } void kruskal(int n) { int numin=0,numax=0,i,j,x,y; sort(e+1,e+cnt+1,cmp); for(i=1,j=cnt;i<=cnt,j>=1;i++,j--) { x=find(e[i].u,f1); y=find(e[i].v,f1); if(x!=y) { f1[x]=y; minn+=e[i].w; numin++;//最小生成树 if(numin>=n) { minn=0; return; } } x=find(e[j].u,f2); y=find(e[j].v,f2); if(x!=y) { f2[x]=y; maxx+=e[j].w; numax++;//最大生成树 if(numax>=n) { maxx=0; return; } } } if(numin!=n-1) { minn=0; } if(numax!=n-1) { maxx=0; } } int main() { int t,n,m,u,v,w,i,j,flag; scanf("%d",&t); fib[1]=fib[2]=1; vis[1]=1; for(i=3;fib[i-1]<=100010;i++) { fib[i]=fib[i-1]+fib[i-2]; vis[fib[i]]=1; } for(i=1;i<=t;i++) { scanf("%d%d",&n,&m); cnt=minn=maxx=flag=0; for(j=1;j<=n;j++) { f1[j]=f2[j]=j; } for(j=1;j<=m;j++) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } kruskal(n); if(minn!=0&&maxx!=0) { for(j=minn;j<=maxx;j++) { if(vis[j]==1) { //printf("Case #%d: ",i); //printf("Yes\n"); printf("YES\n"); flag=1; break; } } if(flag==0) { //printf("Case #%d: ",i); //printf("No\n"); printf("NO\n"); } } else { //printf("Case #%d: ",i); //printf("No\n"); printf("NO\n"); } } return 0; }
- 貌似改输出格式后 \(HDU\) 上 \(WA\) 了,有知道原因的@我。
T2 期末考试 \(0pts\)
- 题面中没有明确表明必定有解,但测试数据表明必定有解。
- 部分分(赛场上没骗到,祭):
- \(n\) 份答案对应分数都为 \(0\) ( \(10\)pts ):
- 设 \(n\) 份答案中第 \(i\) 位共出现了 \(sum[i]\) 种字符,则有:$$ans=\prod\limits_{i=1}^{10}(4-sum[i])$$
- \(n\) 份答案对应分数都为 \(90\) ( \(10\)pts ):
- 设 \(n\) 份答案共中有 \(x\) 份本质不同,则有:\[ans = \left \{ \begin{aligned} &10×C_1^3=10×\frac{3!}{{2}!×1!}=10×3=30 && (x = 1) \\ &C_2^1=\frac{2!}{{1}!×1!}=2 && (x = 2,且两份代码仅有1处答案不同) \\ &1+1=2 && (x = 2,且两份代码仅有2处答案不同,但必定有解) \\ &1 && \text{(otherwise)} \end{aligned} \right. \]
- 设 \(n\) 份答案共中有 \(x\) 份本质不同,则有:
- \(n\) 份答案对应分数都为 \(0\) ( \(10\)pts ):
- 直接爆搜,貌似数据有点差,放过去了 \(O(n×4^n)\)
- 设 \(ans[]\) 临时存储一个答案,检验这个答案的正确性。如果符合题意,则答案总数 \(++\) 。
#include<bits/stdc++.h> using namespace std; #define ll long long #define sort stable_sort #define endl '\n' char s[30000][10],ans[10];//慎用string,不开O2可能会祭 int a[30000],maxx; void dfs(int x,int n) { int i,j,num; if(x==10)//检验临时答案是否正确 { for(i=1;i<=n;i++) { num=0; for(j=0;j<=9;j++) { if(ans[j]==s[i][j]) { num+=10; } } if(num!=a[i])//说明答案不合法 { return; } } maxx++; } else { for(i=1;i<=4;i++)//爆搜临时答案 { ans[x]='A'+i-1; dfs(x+1,n); } } } int main() { int t,n,i,j; cin>>t; for(i=1;i<=t;i++) { cin>>n; maxx=0; for(j=1;j<=n;j++) { cin>>s[j]>>a[j]; } dfs(0,n); cout<<maxx<<endl; } return 0; }
- 正解貌似是 \(meet \ in \ the \ middle\) ,但没听懂,暂时咕了。
T3 麻烦的工作 \(0pts\)
@wangyunbiao: 不可以,总司令
我:不,可以,总司令
@wangyunbiao: 我 \(T3\) 爆零了
我: 我 \(T3\) 也爆零了
- 没听懂讲评,暂时咕了。
- 可参考wkh的。
T4 小X的Galgame \(0pts\)
- 部分分( \(20pts\) ):输出所有边权之和。
- 没听懂讲评,暂时咕了。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/17600780.html,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。