2018 Multi-University Training Contest 1

1001:

 推出公式只需要1/x+1/y+1/z=1的整数解,有2、4、4和3、3、3和2、3、6。但2、3、6得到答案比3、3、3小,故只判断前两种可能。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <string>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <map>
 7 #include <stack>
 8 #include <vector>
 9 #include <queue>
10 #include <set>
11 using namespace std;
12 
13 const int MAX=1e5+5;
14 long long t,n;
15 long long a,b;
16 
17 int main(){
18     scanf("%lld",&t);
19     while(t--){
20         a=b=0;
21         scanf("%lld",&n);
22         if(n%4==0){
23             a=n/2*n/4*n/4;
24         }
25         if(n%3==0)
26             b=n/3*n/3*n/3;
27         if(n%4&&n%3)
28             puts("-1");
29         else
30             printf("%lld\n",max(a,b));
31     }
32     
33     return 0;
34 }
View Code

 

1002:

把每个串能够匹配的处理掉,得到剩余的左括号和右括号数,再按贡献大小排序,最后合并成一个串。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;

const int MAX=1e5+5;
int t,n;
char str[MAX];
struct node{
    int l,r;
}p[MAX];
int ans;

int cmp(node a,node b){
    int tmpa,tmpb;
    tmpa=min(a.l,b.r);
    tmpb=min(a.r,b.l);
    if(tmpa==tmpb)
        return a.l>b.l;
    return tmpa>tmpb;
}

int main(){
    int i,j;
    
    //freopen("1002.in","r",stdin);
    //freopen("1003.out","w",stdout);
    scanf("%d",&t);
    while(t--){
        ans=0;
        scanf("%d",&n);
        for(i=0;i<n;i++){
            scanf("%s",&str);
            int len=strlen(str);
            p[i].l=p[i].r=0;
            for(j=0;j<len;j++){
                if(str[j]=='(') p[i].l++;
                else{
                    if(p[i].l) p[i].l--,ans++;
                    else p[i].r++;        
                }
            }
        }
        sort(p,p+n,cmp);
        int l=0;
        for(i=0;i<n;i++){
            if(p[i].r>l){
                ans+=l;
                l=0;
            }
            else{
                ans+=p[i].r;
                l-=p[i].r;
            }
            l+=p[i].l;
        }
        printf("%d\n",ans*2); 
    }
    
    return 0;
}
View Code

 

1003:

贪心排一下序就行,先按x坐标再按y坐标,每次选三个即可

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
struct point
{
    long long x,y;
    int id;
};
point po[4010];
int n;

void init()
{
    memset(po,0,sizeof(po));
}

bool cmp(const point &a,const point &b)
{
    if(a.y==b.y) return a.x<b.x;
    return a.y<b.y;
}

int main()
{
    int i;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d",&n);
        for(i=1;i<=3*n;i++)
        {
            cout<<i<<endl;
            scanf("%lld%lld",&po[i].x,&po[i].y);
            po[i].id=i;
        }
        sort(po+1,po+1+3*n,cmp);
        int pos=1;
        for(i=1;i<=n;i++)
        {
            printf("%d %d %d\n",po[pos++].id,po[pos++].id,po[pos++].id);
        }
    }
    return 0;
}
View Code

 

1004:

 添加n条端点为[i,i]的长度为1的线段,将所有线段以左端点为第一关键字,线段长度为第二关键字排序,依次处理。设置L,R两个指针和一个小根堆(初始存了1~n的数字),每次处理一条线段时先将L到线段左端点的数字加入小根堆,再把R到线段右端的数字从小根堆中取数字更新。

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 
 7 #define maxn 200000+5
 8 
 9 using namespace std;
10 
11 priority_queue <int,vector<int>,greater<int> > q;
12 
13 struct Data{
14     int l,r,len;
15     bool operator <(const Data &T)const{
16         if(l==T.l) return len>T.len;
17         else return l<T.l;
18     }
19 }t[maxn];
20 
21 int res[maxn];
22 int n,m;
23 
24 int main(){
25     int T;
26     scanf("%d",&T);
27     while(T--){
28         memset(res,0,sizeof(res));
29         scanf("%d%d",&n,&m);
30         while(!q.empty()) q.pop();
31         for(int i=1;i<=n;i++) q.push(i);
32         for(int i=1;i<=m;i++){
33             scanf("%d%d",&t[i].l,&t[i].r);
34             t[i].len=t[i].r-t[i].l+1;
35         }
36         for(int i=1;i<=n;i++) t[++m].l=i,t[m].r=i,t[m].len=1;
37         sort(t+1,t+1+m);
38         int L=1,R=0;
39         for(int i=1;i<=m;i++){
40             while(L<t[i].l) q.push(res[L]),L++;
41             while(R<t[i].r) res[++R]=q.top(),q.pop();
42         }
43         printf("%d",res[1]);
44         for(int i=2;i<=n;i++) printf(" %d",res[i]);
45         puts(""); 
46     }
47     return 0;
48 }
View Code

 

1005:

 

1007:

找规律,打表

首先把a[]序列打表出来:

将相同元素放到同一行发现这样的一个三角形

1

2 2

4 4 4

5

6 6

7

8 8 8 8

发现这个a[]中每个元素出现的次数刚好是因子中所含2的数量+1

然后就好做了,找一找这个三角形规律,注意打表,log*log的复杂度过不了

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
const long long mod=1e9+7;
const long long inv=500000004;
long long  num_2[100],mi[100],biao[100],biao_cnt[100];
long long n,num,sum;
long long ans;

void init()
{
    num=0;
    ans=0;
    sum=0;
}

long long fun(long long now,int i)
{
    long long pos=now;

    long long flag=(pos%mod)*((pos+1)%mod)%mod;
    flag=(flag*inv)%mod;
    long long tmp=flag;
    long long cnt=pos;
    long long t=flag;
    pos/=2;
    while(pos>0)
    {
        tmp=(tmp+((t+now/2)%mod)*inv)%mod;
        cnt+=pos;
        pos/=2;
        t=(((t+now/2)%mod)*inv)%mod;
    }
    tmp=(tmp+(sum%mod*cnt%mod)%mod)%mod;

    biao_cnt[i]=cnt;
    sum+=now;
    return (tmp%mod+mod)%mod;
}

int main()
{
    //freopen("123.in","r",stdin);
    //freopen("123.out","w",stdout);
    int i;
    num_2[0]=0;
    mi[0]=1;
    biao[0]=fun(mi[0],0);
    long long flag=1;
    for(i=1;i<=62;i++)
    {
        flag*=2;
        mi[i]=flag;
        num_2[i]=flag-1;
        sum=0;
        biao[i]=fun(mi[i],i);
   //     cout<<biao_cnt[i]<<endl;
    }
    int t;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%lld",&n);
        long long tmp=n-1;
        for(i=62;i>0;i--)
        {
            if(tmp==0) break;
            if(num_2[i]>tmp) continue;
            num+=(num_2[i]+1)/2;
            tmp-=num_2[i];
        }

        long long cnt=num;
        long long pos=0;
        int xx=62;
        sum=0;
        while(cnt>0)
        {

           for(i=xx;i>=0;i--)
            {
                if(mi[i]<=cnt)
                {
                    pos=mi[i];
                    break;
                }
            }
            long long flag=biao[i];

            flag=(flag+(sum%mod)*(biao_cnt[i]%mod))%mod;
            ans=(ans+flag)%mod;
            cnt-=pos;
            sum+=pos;
        }
        ans=(ans+((num+1)%mod)*(tmp%mod)+1)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

1008:

 MQ-Similar实际上就是 A 和 B 的笛卡尔树一样,这样我们就有了一个二叉树,然后可以在树上分析了。

考虑到B中有元素相同的概率是 0 ,于是可以假设 BB 里面元素互不相同,也就是说可以假定是一个排列。

显然,符合笛卡尔树的排列就是这个树的拓扑序列个数,就是n!/2∏sizei。然后显然每个排列期望的和是n/2,于是答案就是n/2sizei

由于我们只需要知道笛卡尔树的大小,所以可以不通过显性建树,用单调栈维护一下即可

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
const long long mod=1e9+7;
int ai[3000010];
int n;
int st[3000010],head,sum_left[3000010],sum[3000010];
long long inv[1000010];

void init()
{
    head=0;
}

struct FastIO
{
    static const int S = 200;
    int wpos;
    char wbuf[S];
    FastIO() :wpos(0) {}
    inline int xchar()
    {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len) pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos++];
    }
    inline int read()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
}io;


int main()
{
    //freopen("1008.in","r",stdin);
    //freopen("text.out","w",stdout);
    int i,j;
    int t;
    inv[1]=1;
    for(i=2;i<=1000000;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    t=io.read();
    while(t--)
    {
        n=io.read();
        init();
        for(i=1;i<=n;i++)
        {
            ai[i]=io.read();
        }
        for(i=1;i<=n;i++)
        {
            sum[i]=0;
            sum_left[i]=0;
            while(head!=0&&ai[st[head]]<ai[i])
            {
                sum[st[head]]=i-sum_left[st[head]];
                head--;
            }
            if(head==0) sum_left[i]=1;
            else sum_left[i]=st[head]+1;
            st[++head]=i;
        }
        for(i=2;i<=head;i++) sum[st[i]]=n-sum_left[st[i]]+1;
        sum[st[1]]=n;
        long long ans=1;
        for(i=1;i<=n;i++)
        {
            ans=(ans*inv[sum[i]])%mod;
        }
        ans=(ans*n)%mod*inv[2]%mod;
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

1011:

随便算算

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#include <set>
using namespace std;

const int MAX=1e5+5;
int a,b,x,y,t,flag,p;
char str[MAX];

int main(){
    int i;
    
    scanf("%d",&t);
    while(t--){
        x=y=flag=0;
        scanf("%d%d",&a,&b);
        scanf("%s",&str);
        for(i=0;i<strlen(str);i++){
            if(str[i]=='.')
                flag=1;
            if(str[i]=='+')
                p=1;
            if(str[i]=='-')
                p=-1;
            if(flag&&str[i]>='0'&&str[i]<='9')
                y=str[i]-'0';
            if(!flag&&str[i]>='0'&&str[i]<='9'){
                x=str[i]-'0';
                if(str[i+1]>='0'&&str[i+1]<='9'){
                    x*=10;
                    x+=str[i+1]-'0';
                    i++;
                } 
            }
        }
        if(p==1){
            if(x<8){
                int h=8-x;
                a-=h;
                if(a<0) a+=24;
            }
            else{
                int h=x-8;
                a+=h;
                if(a>=24) a-=24;
            }
            int m=6*y;
            b+=m;
            if(b>=60){
                a++;
                if(a>=24) a-=24;
                b-=60;
            }
        }
        else{
            int h=x+8;
            a-=h;
            if(a<0) a+=24;
            int m=6*y;
            b-=m;
            if(b<0){
                a--;
                if(a<0) a+=24;
                b+=60;
            }
        }
        printf("%0.2d:%0.2d\n",a,b);
    }
    
    return 0;
}
View Code

 

posted @ 2018-07-24 09:18  Hetui  阅读(234)  评论(0编辑  收藏  举报