2018 Multi-University Training Contest 1 做题记录
这场题面较短,不翻译了
1001
题解:
大家为什么都能一眼秒题啊qwq
考场上暴力打表找规律,mod 12分类一下,然后发现mod 3和mod 4=0有解否则无解,然后找了一波规律,AC
证明:本质就是1=1/x+1/y+1/z这个不定方程的解
这个不定方程有三组解(2,4,4),(3,3,3),(2,3,6)
其中(2,3,6)一定没有前面的优秀
所以就只有两组解了,mod3=0和mod4=0的情况下就是这两组解
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define maxn 1000005 4 using namespace std; 5 int T; 6 inline void read(int &x) 7 { 8 x=0; 9 char ch=getchar(); 10 while(ch<'0'||ch>'9')ch=getchar(); 11 while('0'<=ch&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); 12 } 13 int main() 14 { 15 scanf("%d",&T); 16 while(T--) 17 { 18 int n; 19 read(n); 20 if(n%3==0)printf("%lld\n",1ll*(n/3)*(n/3)*(n/3)); 21 else if(n%4==0)printf("%lld\n",1ll*(n/2)*(n/4)*(n/4)); 22 else puts("-1"); 23 } 24 return 0; 25 }
1003
题解:
显然按x坐标排序然后选相邻3个为一组就好了
1 #include<bits/stdc++.h> 2 #define maxn 1005 3 using namespace std; 4 int T; 5 int n; 6 struct point 7 { 8 int x,y,id; 9 }p[maxn*3]; 10 bool cmp(point a,point b) 11 { 12 return a.x<b.x; 13 } 14 int main() 15 { 16 scanf("%d",&T); 17 while(T--) 18 { 19 scanf("%d",&n); 20 for(int i=1;i<=n*3;++i)scanf("%d%d",&p[i].x,&p[i].y),p[i].id=i; 21 sort(p+1,p+3*n+1,cmp); 22 for(int i=1;i<=n*3;++i) 23 { 24 printf("%d",p[i].id); 25 if(!(i%3))puts("");else printf(" "); 26 } 27 } 28 return 0; 29 }
1004
题解:
显然贪心是对的,我们每次尽量找最小的没出现过的数就行(mex)
然后我们拿一个小根堆维护就行,实现直接用pq
1 #include<bits/stdc++.h> 2 #define maxn 100005 3 using namespace std; 4 int T; 5 int n,m; 6 struct Line 7 { 8 int l,r; 9 }a[maxn],b[maxn]; 10 bool cmp(Line a,Line b) 11 { 12 if(a.l==b.l)return a.r<b.r; 13 return a.l<b.l; 14 } 15 int Ans[maxn]; 16 int main() 17 { 18 scanf("%d",&T); 19 while(T--) 20 { 21 scanf("%d%d",&n,&m); 22 for(int i=1;i<=m;++i)scanf("%d%d",&a[i].l,&a[i].r); 23 sort(a+1,a+m+1,cmp); 24 int cnt=0; 25 for(int i=1;i<=m;++i)if(a[i].r>b[cnt].r)b[++cnt]=a[i]; 26 int tot=0; 27 priority_queue<int,vector<int>,greater<int> > q; 28 int l=0,r=0; 29 for(int i=1;i<=cnt;++i) 30 { 31 if(r<=b[i].l) 32 { 33 tot=0; 34 while(!q.empty())q.pop(); 35 for(int j=b[i].l;j<=b[i].r;++j)Ans[j]=++tot; 36 l=b[i].l,r=b[i].r+1; 37 } 38 else 39 { 40 while(l<b[i].l) 41 { 42 q.push(Ans[l]);l++; 43 } 44 while(r<=b[i].r) 45 { 46 if(!q.empty())Ans[r]=q.top(),q.pop(); 47 else Ans[r]=++tot; 48 ++r; 49 } 50 } 51 } 52 for(int i=1;i<=n;++i)if(!Ans[i])Ans[i]=1; 53 for(int i=1;i<=n;++i) 54 { 55 printf("%d",Ans[i]); 56 if(i!=n)printf(" ");else puts(""); 57 } 58 for(int i=1;i<=n;++i)Ans[i]=0; 59 } 60 return 0; 61 }
1008
题解:
两个序列RMQ similar等价于两个序列笛卡尔树形状相同
然后构建笛卡尔树,考虑每个元素随机情况下成为子树最大值的概率为1/size[u]
然后形成这样的树的概率为(1/∏size[i])
乘以总和的期望大小n/2
答案就是(n/2)*(1/∏size[i])
所以建出笛卡尔树然后dp一下就行
dfs貌似会爆栈,bfs大法保平安
1 #include<bits/stdc++.h> 2 #define maxn 1000005 3 #define ll long long 4 using namespace std; 5 const ll mod=1000000007; 6 ll inv[maxn]; 7 int T,n; 8 pair<int,int> a[maxn]; 9 int ls[maxn],rs[maxn],fa[maxn],rt,size[maxn]; 10 int stk[maxn],top; 11 void buildtree() 12 { 13 for(int i=1;i<=n;++i)ls[i]=rs[i]=fa[i]=stk[i]=size[i]=0; 14 rt=0;top=0; 15 for(int i=1;i<=n;++i) 16 { 17 int k=top; 18 while(k&&a[stk[k]]>a[i])--k; 19 if(k)rs[stk[k]]=i,fa[i]=stk[k]; 20 if(k<top)ls[i]=stk[k+1],fa[stk[k+1]]=i; 21 top=k;stk[++top]=i; 22 } 23 for(int i=1;i<=n;++i)if(!fa[i])rt=i; 24 } 25 int c[maxn]; 26 void bfs() 27 { 28 int cnt=0; 29 queue<int> q;q.push(rt); 30 while(!q.empty()) 31 { 32 int u=q.front();q.pop(); 33 c[++cnt]=u; 34 if(ls[u])q.push(ls[u]); 35 if(rs[u])q.push(rs[u]); 36 } 37 for(int i=1;i<=n;++i)size[i]=1; 38 for(int i=n;i;--i) 39 { 40 int x=c[i]; 41 size[fa[x]]+=size[x]; 42 } 43 } 44 int main() 45 { 46 inv[1]=1; 47 for(int i=2;i<=1000000;++i)inv[i]=inv[mod%i]*(mod-mod/i)%mod; 48 scanf("%d",&T); 49 while(T--) 50 { 51 scanf("%d",&n); 52 for(int x,i=1;i<=n;++i) 53 { 54 scanf("%d",&x);a[i]=make_pair(-x,i); 55 } 56 buildtree(); 57 bfs(); 58 ll ans=n; 59 ans=ans*inv[2]%mod; 60 for(int i=1;i<=n;++i)ans=ans*inv[size[i]]%mod; 61 printf("%lld\n",ans); 62 } 63 return 0; 64 }
1011
题解:
模拟,注意各种细节
1 #include<bits/stdc++.h> 2 using namespace std; 3 const double eps=1e-6; 4 int T; 5 double h,m; 6 int main() 7 { 8 scanf("%d",&T); 9 while(T--) 10 { 11 scanf("%lf%lf",&h,&m); 12 double dt=0,f=1; 13 char ch=getchar(); 14 while(ch!='+'&&ch!='-')ch=getchar(); 15 if(ch=='-')f=-1; 16 scanf("%lf",&dt); 17 dt*=f;dt-=8; 18 double dx=(int)dt;double dy=dt-dx; 19 h+=dx;m+=dy*60; 20 while(m<eps)m+=60,h-=1; 21 while(m>=60-eps)m-=60,h+=1; 22 while(h<eps)h+=24; 23 while(h>=24-eps)h-=24; 24 int hh=(int)(h+0.1),mm=(int)(m+0.1); 25 printf("%02d:%02d\n",hh,mm); 26 } 27 return 0; 28 }
还有好几题的坑待填qwq