zoukankan      html  css  js  c++  java
  • Codeforces Round #630 (Div. 2)(A-D)

    A 在一个方格可以多次,那么可以在相邻的两个方格来回走,然后会在左右或者的一个方向剩下几步,判断是否越边界就可以了,除此之外还要特判x1== x2或者y1== y2(刚才那样有一个前提条件,那个方向上得能迈出去,感谢样例)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100010;
    typedef long long ll;
    int t,a,b,c,d,x,y,x1,x2,y1,y2;
    int main()
    {
    	cin>>t;
    	while(t--)
    	{
    		cin>>a>>b>>c>>d>>x>>y>>x1>>y1>>x2>>y2;
    		if(x==x1&&x1==x2&&(a||b))
    		{
    			puts("No");
    			continue;
    		}
    		if(y==y1&&y==y2&&(c||d))
    		{
    			puts("No");
    			continue;
    		}
    		if(a>=b) a=a-b,b=0;
    		else b=b-a,a=0;
    		if(c>=d) c=c-d,d=0;
    		else d=d-c,c=0;
    		if(x-x1>=a&&x2-x>=b&&y-y1>=c&&y2-y>=d) puts("Yes");
    		else puts("No"); 
    	}
    	
    	return 0;
      }  
    

    B 相同颜色的数的gcd必须大于1,那么我们可以给有形同质因子的数全部染上相同的颜色,然后就分解质因子呗,第11个质因子是31,31*37>1000了,所以前11个质质数完全可以处理1000以内的所有合数。给每个出现的质数一个颜色,每个合数中选一个质因数染色

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100010;
    typedef long long ll;
    int t,n;
    int a[N],c[N];
    int main()
    {
    	scanf("%d",&t);
    	while(t--)
    	{
    		scanf("%d",&n);
    		int num[10000]={0},m=1;//num标记质因数的颜色
    		for(int i=1;i<=n;i++) 
    		{
    			scanf("%d",a+i);
    			for(int j=2;j*j<=a[i];j++)//分解质因数
    			{
    				if(a[i]%j==0) 
    				{
    					if(num[j]) c[i]=num[j];
    					else c[i]=num[j]=m++;
    					break;
    				}
    				while(a[i]%j==0) a[i]/=j;
    			}
    		}
    		printf("%d
    ",m-1);
    		for(int i=1;i<=n;i++) printf("%d ",c[i]);
    		puts("");
    	}
    	return 0;
      }  
    

    C 根据定义si=s[k+i],那么就有
    s1=s[1+k]=s[1+2k]…
    sn=s[n-k]=s[n-2
    k]…
    然后还得是回文串 s1=sn,联立一下这些位置必须相等,找最多的字母次数,总的这些位置的数量减它就是这些位置的最小变化,其他位置一样,k是奇数还需要特判一下。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=200010;
    typedef long long ll;
    int t,n,k;
    int a[N],c[N];
    char s[N];
    int main()
    {
    	scanf("%d",&t);
    	while(t--)
    	{
    		scanf("%d %d ",&n,&k);
    		scanf("%s",s+1);
    		int ans=0;
    		for(int i=1;i<=(k+1)/2;i++)
    		{
    			int num[30]={0};//别忘了清0
    			if((k&1)&&i==(k+1)/2)//这个时候的i和k-i+1相等,所以得特判
    				for(int j=i;j<=n;j+=k) num[s[j]-'a']++;
    			 else 
    			 {
    			 	for(int j=i;j<=n;j+=k) num[s[j]-'a']++;
    			 	for(int j=k-i+1;j<=n;j+=k) num[s[j]-'a']++;
    			 }
    			 int sum=0,m=0;
    			 for(int i=0;i<26;i++) m=max(num[i],m),sum+=num[i]; 
    			 ans+=(sum-m);
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
      }  
    

    D 他的错误dp是因为&过程中的最大值不一定能使后面的&操作最大
    要使最优解与他输出的差值为k,感觉两个值分别等 k和0是比较好构造吧,所以我的目的是使最优解为k,而dp输出0,假设点[n,m]位置为k,为方便构造减少分支情况就把所有情况都从一个方向来,就令[n-1,m]为0,这个方向一定为0。
    接下来就是使 dp[n][m-1]&k 等0,而[n,m-1]可以得到的较小的值&k等k,什么值&k等0呢,k按位取反(令他为m)。
    然后看一下m的范围是3e5是不是一定比1e5范围的k大,3e5以内的数二进制最多有19位,而1e5以内最多有17位,所以k的18位上一定是0,那么m的18位就一定是1了,所以m一定大于k 。
    所以就可构造[n-1,m-1]为m,[n,m-2]为k,令s=2^18-1(二进制下各位都是1,小于3e5的最大值,&任何数的结果都等原数),其他位所有数都为s,这样两行三列足矣,所以构造的矩阵就是 s m 0
    k s k

    #include<bits/stdc++.h>
    using namespace std;
    const int N=200010;
    typedef long long ll;
    int t,n,k,m,s;
    int a[N],c[N];
    char s[N];
    int main()
    {
    		cin>>k;
    		for(int i=0;i<20&&(m+(1<<i)<3e5);i++)
    		{
    			s+=(1<<i);
    			if((k&(1<<i))==0&&m+(1<<i)<3e5)
    				m+=(1<<i);
    		}
    		cout<<2<<' '<<3<<endl;
    		cout<<s<<' '<<k<<' '<<0<<endl;
    		cout<<m<<' '<<s<<' '<<k;
    	return 0;
      }  
    

    第一次过四题体验挺好hh,E太难了,溜了

  • 相关阅读:
    Linux CentOS 安装 宝塔
    Linux CentOS 基本命令
    Linux CentOS 各个版本的区别
    OSI物理层之数据通信基础知识
    如何在集群里服役新节点、退役旧节点(DataNode)
    MapReduce的运行流程概述
    MapReduce计算框架的核心编程思想
    解决HDFS上小文件的存储
    计算机网络体系架构之OSI七层模型、TCP/IP四层模型
    集群里常见进程的端口号
  • 原文地址:https://www.cnblogs.com/neflibata/p/12871767.html
Copyright © 2011-2022 走看看