zoukankan      html  css  js  c++  java
  • Codeforces Round #741 (Div. 2)部分题题解

    我果然还是太菜了,就写了两道题....真是水死了....

    A The Miracle and the Sleeper

    简化题意:给定(l,r),求(a)%(b)的最大值,其中(r>=a>=b>=l).
    这里规定了是大的数模小的数,考虑选定一个(b),显然(a)必须比他大,则b%b=0,(b+1)%b=1,(b+2)%b=2...(2b-1)%b=b-1,之后就又从0开始到b-1,显然若(2b-1<=r)的话我们就能取到在模b的意义下的最大值,还有的是我们想让这个b足够大,才能满足我们的期望。也就是说对于一个数x在其2x-1处恰取到最大值。那么最好的情况就是2bx-1=r,这样的话,恰好在r处取到模bx意义下的最大值。这样比bx大的,取不到bx-1,比bx小的,更取不到bx-1。但这只是奇数的情况,若r为偶数的话怎么办,有两种想法,让r-1恰取到最大值,和r+1恰取到最大值,经过计算发现这样的话得到的值都是一样的都为r/2。但让r+1取到最大值,要求的值为r/2+1比r-1取到最大值要求的值为r/2,相比下前者更容易满足l的限制。还有一个问题那如果我们要求的恰好取到最大值的x(或b)小于l怎么办呢,你想一下,你的x是从x开始到r恰好取到最大值,但x小于l,那说明从l开始到r都取不到l-1,此时一定数从l开始更优!完毕!

    //不等,不问,不犹豫,不回头.
    #include<bits/stdc++.h>
    #define _ 0
    #define ls p<<1
    #define db double
    #define rs p<<1|1
    #define P 1000000007
    #define ll long long
    #define INF 1000000000
    #define get(x) x=read()
    #define PLI pair<ll,int>
    #define PII pair<int,int>
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(x,y,z) for(int x=y;x<=z;++x)
    #define fep(x,y,z) for(int x=y;x>=z;--x)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
     
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
     
    int main()
    {
        //freopen("1.in","r",stdin);
    	int get(T);
    	while(T--)
    	{
    		int get(l),get(r);
    		if(r%2==0)
    		{
    			if(r/2+1>=l) cout<<r/2-1<<endl;
    			else cout<<r-l<<endl;
    		}
    		else
    		{
    			int s=r+1;
    			if(s/2>=l) cout<<s/2-1<<endl;
    			else cout<<r-l<<endl; 
    		}
    	}
        return (0^_^0);
    }
    //以吾之血,铸吾最后的亡魂.
    

    B. Scenes From a Memory

    B题啊,气人我把57当成质数了....气死!57=19*3,估计我能记一辈子了...
    这个题我们其实可以将所有的答案给预先找出来,这样直接查找就行了,答案最多是两位数。

    //不等,不问,不犹豫,不回头.
    #include<bits/stdc++.h>
    #define _ 0
    #define ls p<<1
    #define db double
    #define rs p<<1|1
    #define P 1000000007
    #define ll long long
    #define INF 1000000000
    #define get(x) x=read()
    #define PLI pair<ll,int>
    #define PII pair<int,int>
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(x,y,z) for(int x=y;x<=z;++x)
    #define fep(x,y,z) for(int x=y;x>=z;--x)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=100;
    int vis[N],n;
    char c[N];
     
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
     
    int main()
    {
    //freopen("1.in","r",stdin);
        int get(T);
    	while(T--)
    	{
    		get(n);scanf("%s",c+1);
    		int id=0;
    		rep(i,1,n) 
    		{
    			if(c[i]=='1'||c[i]=='4'||c[i]=='6'||c[i]=='8'||c[i]=='9')
    			{
    				id=c[i]-'0';
    				break;
    			}
    		}
    		if(id) {put(1);put(id);continue;}
    		memset(vis,0,sizeof(vis));
    		rep(i,1,n)
    		{
    			if(c[i]=='2'&&i!=1)
    			{
    				id=(c[i-1]-'0')*10+2;
    				break;
    			} 
    			else if(c[i]=='5'&&i!=1)
    			{
    				id=(c[i-1]-'0')*10+5;
    				break;
    			}
    			else if(c[i]=='3'&&vis[3]) 
    			{
    				id=33;break;
    			}
    			else if(c[i]=='7'&&vis[7])
    			{
    				id=77;break;
    			} 
    			else if(c[i]=='7'&&vis[2])
    			{
    				id=27;break;
    			}
    			else if(c[i]=='7'&&vis[5])
    			{
    				id=57;break;
    			}
    			vis[c[i]-'0']=1;
    		}
    		put(2);put(id);
    	}
        return (0^_^0);
    }
    //以吾之血,铸吾最后的亡魂.
    

    C. Rings

    看完题解的我眼泪流下来...
    简化题意:给定一个长度为n的01串表示一个二进制数,你需要截取两个不同的且长度都必须大于等于(frac{n}{2})(向下取整)的区间,使得这两个区间转换成两个十进制数后互为倍数关系,这不妥妥的构造题吗,我怎么死在上面了....
    由于2进制数肯定和2有关系,我们先尝试用2的倍数看能不能搞事情,容易发现,我们若截取了l,r,考虑l-1,r为若l-1为0,那妥妥的一倍关系就行,考虑l,r+1,若r+1为0,那不就是两倍的关系吗?找到什么规律了吗?也就是说只要这个01串中有0的话,我们就可以顺着这个0在前面(或后面)截取长度为n/2的字串就可以构造答案了,为什么有0就行,因为往前往后都可以构造,这样的话一定能构造出答案。那接下来考虑全是1的情况,那这不是更是白给吗?我们随便截取两端全是1的就是1倍的关系。完毕!

    //不等,不问,不犹豫,不回头.
    #include<bits/stdc++.h>
    #define _ 0
    #define ls p<<1
    #define db double
    #define rs p<<1|1
    #define P 1000000007
    #define ll long long
    #define INF 1000000000
    #define get(x) x=read()
    #define PLI pair<ll,int>
    #define PII pair<int,int>
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(x,y,z) for(int x=y;x<=z;++x)
    #define fep(x,y,z) for(int x=y;x>=z;--x)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=2e4+10;
    int n,T;
    char c[N]; 
    
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
    	get(T);
    	while(T--)
    	{
    		get(n);
    		scanf("%s",c+1);
    		bool flag=false;
    		rep(i,1,n)
    		{
    			if(c[i]=='0')
    			{
    				flag=true;
    				if(i-n/2>=1)
    					printf("%d %d %d %d
    ",i-n/2,i,i-n/2,i-1);
    				else if(i+n/2<=n)
    					printf("%d %d %d %d
    ",i,i+n/2,i+1,i+n/2);
    				break;
    			} 
    		}
    		if(flag) continue;
    		printf("%d %d %d %d
    ",1,n/2,2,n/2+1);
    	}
        return (0^_^0);
    }
    //以吾之血,铸吾最后的亡魂.
    
    

    D1. Two Hundred Twenty One (easy version)

    这个题的题意是真的难理解啊....
    简化题意:给你一个序列,其中序列中每个数的值要么1要么-1,且每个位置上都有一个符号满足奇数位为+,偶数位为-,给你q个询问,每个询问给你一个区间,求区间里至少去掉多少个数,才能使得这个区间和为0,注意去掉一个数后,后面所有的数都向前平移。其实这句话的意思就是所有数的符号变为前面数的符号。考虑去掉一个数,对前面数肯定没影响,对后面的数的影响就是所有数的符号取反,其实就是后面数的和取反。考虑对于一个区间而言,若区间和为奇数,那么肯定存在一个中间的数,其前面的和等于后面的和,那么我们将这个数去掉,后面的数取反,和为0为最优的情况,那和为偶数的呢?一次显然不够,那我么可以随便去掉一个数,使其和变为奇数,再按上述操作就行。完毕!

    //不等,不问,不犹豫,不回头.
    #include<bits/stdc++.h>
    #define _ 0
    #define ls p<<1
    #define db double
    #define rs p<<1|1
    #define P 1000000007
    #define ll long long
    #define INF 1000000000
    #define get(x) x=read()
    #define PLI pair<ll,int>
    #define PII pair<int,int>
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(x,y,z) for(int x=y;x<=z;++x)
    #define fep(x,y,z) for(int x=y;x>=z;--x)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=3e5+10;
    int T,a[N],n,q;
    char c[N]; 
    
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
    	get(T);
    	while(T--)
    	{
    		get(n);get(q);
    		scanf("%s",c+1);
    		rep(i,1,n) a[i]=a[i-1]+(((c[i]=='+'&&i%2==1)||(c[i]=='-'&&i%2==0))?1:-1);
    		rep(i,1,q)
    		{
    			int get(x),get(y);
    			int s=a[y]-a[x-1];
    			if(s==0) put(0);
    			else if((s%2+2)%2==1) put(1);
    			else put(2);
    		}
    	}
        return (0^_^0);
    }
    //以吾之血,铸吾最后的亡魂.
    
    

    D2. Two Hundred Twenty One (hard version)

    这个在上个的基础上要求输出方案。
    考虑奇数的话,我们想要找到那个特殊的位置,直接二分就行。
    偶数的话,我们可以将区间左端点去掉,再二分。

  • 相关阅读:
    Android系统自带样式(android:theme)详解-(转)
    android 查看解压后的.xml文件代码(axmlprinter2)
    android 反编译apktool工具
    Android 解读.apk解压后文件详细说明
    android 利用线程刷新UI方法
    (转)android.intent.action.MAIN与android.intent.category.LAUNCHER
    android xml 布局错误(黑掉了)Missing styles. Is the correct theme chosen for this layout?
    Android应用程序“.R文件”消失怎么办
    android WebView网页浏览器
    Android 命名规范 (提高代码可以读性) -转
  • 原文地址:https://www.cnblogs.com/gcfer/p/15195223.html
Copyright © 2011-2022 走看看