2018 Multi-University Training Contest 1 做题记录

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

猜你喜欢

转载自www.cnblogs.com/uuzlove/p/9382835.html