zoukankan      html  css  js  c++  java
  • 【20170902校内模拟赛】

    T1 卡片(card)

    Description

    lrb喜欢玩卡牌。他手上现在有n张牌,每张牌的颜色为红绿蓝中的一种。现在他有两种操作。一是可以将两张任意位置的不同色的牌换成一张第三种颜色的牌;二是可以将任意位置的两张相同颜色的牌换成一张该颜色的牌。两个操作后都可以将生成的牌放到任意位置。现在他想知道,最后一张牌可能是什么颜色的。

    Input

    第一行输入一个n,表示卡牌数量。
    第二行输入一个由’B’,’G’,’R’组成的长度为n的字符串,分别表示卡牌的颜色为蓝色、绿色、红色中的一种。

    Output

    输出’B’,’G’,’R’中的若干个字母,按字典序输出。代表可能的最后一张牌的颜色。

    Sample Input 1

    2
    RB

    Sample Output 1

    G

    Sample Input 2

    3
    GRG

    Sample Output 2

    BR

    Sample Input 3

    4
    BBBB

    Sample Output 3

    B

    Hint

    对于100%的数据,n≤200

    Solution

    各种特判就行了。。。分支结构题

    Code

    #include <stdio.h>
    #define R register
    #define Filename "card"
    inline int read(){
    	R int x; R bool f; R char c;
    	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
    	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
    	return f?-x:x;
    }
    int T[3],n,cnt,B[3];
    int main(){
    #ifndef Debug
    	freopen(Filename".in","r",stdin);
    	freopen(Filename".out","w",stdout);
    #endif
    	n=read();
    	for (R int i=1; i<=n; ++i){
    		R char c=getchar();
    		while(c<'A'||c>'Z') c=getchar();
    		if (c=='B') ++T[0];
    		if (c=='G') ++T[1];
    		if (c=='R') ++T[2];
    	}
    	for (R int i=0; i<3; ++i) cnt+=(T[i]>1),B[i]=(T[i]>1);
    	if (cnt>1) puts("BGR");
    	else{
    		if (T[0]&&T[1]&&T[2]) puts("BGR");
    		else{
    			if (!cnt){
    				for (R int i=0; i<3; ++i) cnt+=(bool)(T[i]);
    				if (cnt==1){
    					if (T[0]) puts("B");
    					if (T[1]) puts("G");
    					if (T[2]) puts("R");
    				}else{
    					if (T[0]&&T[1]) puts("R");
    					if (T[0]&&T[2]) puts("G");
    					if (T[1]&&T[2]) puts("B");
    				}
    			}else{
    				R int p=-1;
    				for (R int i=0; i<3; ++i){
    					if (B[i]) cnt=i;
    					if (T[i]==1) p=i;
    				}
    				if (p==-1){
    					if (cnt==0) puts("B");
    					if (cnt==1) puts("G");
    					if (cnt==2) puts("R");
    				}else{
    					if (cnt==0) puts("GR");
    					if (cnt==1) puts("BR");
    					if (cnt==2) puts("BG");
    				}
    			}
    		}
    	}
    #ifndef Debug
    	fclose(stdin); fclose(stdout);
    #endif
    	return 0;
    }
    

    T2 取数(win)

    Description

    lrb目前有n个数字,他想知道这n个数中选出若干个数,平均数减中位数的最大值是多少。可以证明,对于一个递增数列a,如果(a_w)是平均数减中位数最大时的中位数,l表示在w两边分别取相邻数字的数量,f(w,l)表示以(a_w)为中位数,在w两侧各取相邻l个数时平均数减中位数的值,那么f(w,l)为关于l的单峰函数。

    Input

    第一行为n,为数字个数。
    第二行有n个数,分别代表n个数字。

    Output

    输出一个数,为平均数减中位数的最大值,保留两位小数。

    Sample Input

    4
    1 2 3 4

    Sample Output

    0.33

    Hint

    对于60%的数据,n≤21
    对于75%的数据,n≤2000
    对于100%的数据,(n≤10^{5},0≤a_{i} ≤ 10^{6})

    Solution

    显然对于选定的中位数,选取l个比它小的尽量大的数,以及l个比它大的尽量大的数可以使得平均数最优,可以证明这个平均数是关于l的单峰函数,故可以使用三分得出l的最优值,枚举所有中位数即可。
    时间效率(O(n log_{frac {3}{2}} n)).

    Code

    #include <stdio.h>
    #include <algorithm>
    #define MN 100005
    #define ll long long
    #define R register
    #define eps 1e-5
    #define Filename "win"
    inline int read(){
    	R int x; R bool f; R char c;
    	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
    	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
    	return f?-x:x;
    }
    ll f[MN];int n;double ans;
    inline int min(int a,int b){return a<b?a:b;}
    inline double max(double a,double b){return a-b>eps?a:b;}
    inline ll getsum(int k,int l){return f[n]-f[n-l]+f[k]-f[k-l-1];}
    int search(int l,int r,int k,int kk){
    	if (l==r) return l;
    	R int p1=(r-l)/3+l,p2=r-(r-l)/3;
    	if (1.0*getsum(k,p2)/(2*p2+kk)-1.0*getsum(k,p1)/(2*p1+kk)>eps) return search(p1+1,r,k,kk);
    	return search(l,p2-1,k,kk);
    }
    int main(){
    #ifndef Debug
    	freopen(Filename".in","r",stdin);
    	freopen(Filename".out","w",stdout);
    #endif
    	n=read();for (R int i=1; i<=n; ++i) f[i]=read();
    	std::sort(f+1,f+n+1);
    	for (R int i=2; i<=n; ++i) f[i]+=f[i-1];
    	for (R int i=2; i<n; ++i){
    		R int tmp=search(1,min(i-1,n-i),i,1);R double ttmp;
    		ttmp=1.0*(f[i]-f[i-tmp-1]+f[n]-f[n-tmp])/(2.0*tmp+1.0)-(f[i]-f[i-1]);
    		ans=max(ans,ttmp);if (i<n-1){
    			tmp=search(1,min(i-1,n-i-1),i,2);
    			ttmp=1.0*(f[i+1]-f[i-tmp-1]+f[n]-f[n-tmp])/(2.0*tmp+2.0)-(f[i+1]-f[i-1])/2.0;
    			ans=max(ans,ttmp);
    		}
    	}printf("%.2lf",ans);
    #ifndef Debug
    	fclose(stdin); fclose(stdout);
    #endif
    	return 0;
    }
    

    T3 密码(key)

    Description

    lrb去柜员机取钱,并输入了他的四位密码。但是这一切都被一个黑帮拍摄了下来。幸好,这一次他的银行卡里并没有剩余任何钱。lrb知道了他的账户被异常登录后十分害怕,然后修改了他的密码。从此以后他为了不被看出密码,他开始“徐晃”。但这一切还是被拍摄了下来,拍摄多次以后,这个黑帮找到了你,希望你在一秒内帮他算出lrb的可能使用的密码数量。

    Input

    第一行输入一个n,为lrb被拍摄的动作次数。
    接下来n行,每行第一个数为t,表示lrb接下来的手指移动次数,接下来为一个长度为t的数字串,表示lrb手指经过的轨迹。lrb手指经过的位置,可能没有按,也有可能按了多次。

    Output

    输出一行,为可能的密码数量。

    Sample Input

    2
    3 123
    3 234

    Sample Output

    5

    Hint

    设所有轨迹串的总长度为L。
    对于35%的数据,L≤5000;
    对于100%的数据,(1≤n≤1000,1≤t≤10^{4},L≤10^{6})

    Solution

    这道题有一个十分显然简单思路(想不到的都是有病,such as me)
    我们只要枚举所有的密码就好了
    然后就是如何check一个密码是否成立。
    我们只要开一个数组记录从每一位开始,后面的第一个0-9分别在第几位,如果都能够找到,那么密码合法。
    如此判断反复判断n次,就可以得到这个密码是否完全成立。
    时间复杂度为(O(10^{4}n))

    Code

    #include <stdio.h>
    #define MN 1005
    #define ML 1000005
    #define R register
    #define Filename "key"
    inline int read(){
    	R int x; R bool f; R char c;
    	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
    	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
    	return f?-x:x;
    }
    int f[ML][10],ans,n,t[MN]; char c[ML];
    int main(){
    
    #ifndef Debug
    	freopen(Filename".in","r",stdin);
    	freopen(Filename".out","w",stdout);
    #endif
    	n=read();for (R int i=1; i<=n; ++i) t[i]=read()+t[i-1],scanf("%s",c+t[i-1]);
    	for (R int i=0; i<10; ++i) f[t[n]][i]=t[n];
    	for(R int i=t[n]-1; i>=0; --i)
    		for(R int j=0; j<10; ++j) f[i][j]=f[i+1][j],f[i][c[i]-'0']=i;
    	for (R int a=0; a<10; ++a)
    		for (R int b=0; b<10; ++b)
    			for (R int c=0; c<10; ++c)
    				for (R int d=0; d<10; ++d){
    					R int cnt=0;for (R int i=0; i<n; ++i) 
    						if (f[f[f[f[t[i]][a]][b]][c]][d]<t[i+1]) cnt++;
    					ans+=(cnt==n);
    				}printf("%d
    ",ans);
    #ifndef Debug
    	fclose(stdin); fclose(stdout);
    #endif
    	return 0;
    }
    

    T4 三角之恋(tri)

    Description

    给出平面上的n个等腰直角三角形。每个三角形用3个整数描述x,y,m(m>0)。一个三角形的3个顶点分别是(x,y),(x+m,y)和(x,y+m)。
    你的任务是计算这些三角形覆盖的总面积。

    Input

    第一行为n,为三角形个数。
    接下来每行三个数(x_{i},y_{i},m_{i}),用于描述一个三角形。

    Output

    输出一个数,为这些三角形覆盖的总面积,保留一位小数。

    Sample Input

    5
    -5 -3 6
    -1 -2 3
    0 0 2
    -2 2 1
    -4 -1 2

    Sample Output

    24.5

    Hint

    (n≤5000,|x_{i},y_{i} |≤5*10^{8},1≤m_{i}≤10^{9})

    Solution

    利用一条扫描线,在离散之后的平面内计算。看成一个个长方形,则只有未被覆盖与覆盖两种可能,处理一下即可,时间效率(O(n^{2}))

    Code

    #include <stdio.h>
    #include <algorithm>
    #define MN 5005
    #define R register
    #define min(a,b) ((a)<(b)?(a):(b))
    #define ll long long
    #define inf 0x7fffffff
    #define Filename "tri"
    inline int read(){
    	R int x; R bool f; R char c;
    	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
    	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
    	return f?-x:x;
    }
    int n,xn,yn,tmp,sn,X[MN<<1],Y[MN<<1];
    bool used[MN<<1];ll ans;
    struct rt{
    	int x,y,m,tx,ty,x2;
    }a[MN],s[MN];
    inline bool cmp(rt a,rt b){return (a.y<b.y||(a.y==b.y&&(a.x<b.x||(a.x==b.x&&a.tx<b.tx))));}
    inline void calc(){
    	R int to=Y[tmp+1]-Y[tmp];
    	for (R int i=s[1].x,j=1,r; X[i]<=s[sn].x2; ++i){
    		while (j<sn&&i>=s[j+1].x) ++j;
    		if (X[i]>=s[j].x2) continue;
            r=min(X[i+1],s[j].x2);
            ans+=2ll*(r-X[i])*to;
            if (r>s[j].x2-to){
                if (X[i]<s[j].x2-to){
                    R int l=r-(s[j].x2-to);
                    ans-=(ll)l*l;
                }
                else{
                    ans-=(ll)(r-X[i])*(r-X[i]);
                    R int l=X[i]-(s[j].x2-to);
                    ans-=2ll*l*(r-X[i]);
                }
            }
    	}++tmp;
        for (R int i=1; i<=sn; ++i)
            if (s[i].ty<=tmp) used[i]=0; 
            else{
                used[i]=1;
                s[i].x2=X[s[i].tx]-(Y[tmp]-Y[s[i].y]);
            }
        R int l=sn; sn=0;for (R int i=1; i<=l; ++i)
            if (used[i]) s[++sn]=s[i];
    }
    int main(){
    #ifndef Debug
    	freopen(Filename".in","r",stdin);
    	freopen(Filename".out","w",stdout);
    #endif
    	n=read();for (R int i=1; i<=n; ++i){
    		a[i].x=read(),a[i].y=read(),a[i].m=read();
    		X[++xn]=a[i].x,X[++xn]=a[i].x+a[i].m;
            Y[++yn]=a[i].y,Y[++yn]=a[i].y+a[i].m;
    	}std::sort(X+1,X+xn+1);std::sort(Y+1,Y+yn+1);
        xn=std::unique(X+1,X+xn+1)-X-1;yn=std::unique(Y+1,Y+yn+1)-Y-1;
        Y[yn+1]=X[xn+1]=inf;
        for (R int i=1; i<=n; ++i){
        	a[i].tx=std::lower_bound(X+1,X+xn+1,a[i].x+a[i].m)-X;
            a[i].ty=std::lower_bound(Y+1,Y+yn+1,a[i].y+a[i].m)-Y;
            a[i].x=std::lower_bound(X+1,X+xn+1,a[i].x)-X;
            a[i].y=std::lower_bound(Y+1,Y+yn+1,a[i].y)-Y;
            a[i].x2=X[a[i].tx];
    	}std::sort(a+1,a+n+1,cmp);a[n+1].y=yn+1;
    	s[sn=1]=a[1]; tmp=a[1].y; s[0].x2=-inf;
    	for (R int i=2; i<=n+1; ++i){
    		while(sn&&a[i].y>tmp) calc();
    		if (tmp<a[i].y) tmp=a[i].y;R bool flag=0;
            for (R int j=1; j<=sn; ++j)
                if (a[i].x<s[j].x){
                    if (a[i].x2<=s[j-1].x2) break;
                    for (int k=sn; k>=j; --k) s[k+1]=s[k];
                    s[j]=a[i];int l=sn+1; sn=j;
                    for (R int k=j+1; k<=l; ++k)
                        if (s[k].x2>s[j].x2) s[++sn]=s[k];
                    flag=1;
                }
            if (!flag&&a[i].x2>s[sn].x2) s[++sn]=a[i];
    	}
    	if (ans&1) printf("%lld.5",ans/2); else printf("%lld.0",ans/2);
    #ifndef Debug
    	fclose(stdin); fclose(stdout);
    #endif
    	return 0;
    }
    
  • 相关阅读:
    Maven导入com.google.common.collect jar包
    poj 2192 Zipper
    poj 3278 Catch That Cow
    poj 2488 A Knight's Journey
    poj 3982 序列
    poj 2109 Power of Cryptography
    poj 3258 3273
    java中大数的一些基本运算
    hdu 1715 大菲波数
    最小生成树模板
  • 原文地址:https://www.cnblogs.com/Melacau/p/Test_20170902.html
Copyright © 2011-2022 走看看