CodeForces Round 630(div2)部分题解

很久没做程序设计题目了,状态下滑的有些厉害。

A.Exercising Walk
原题链接:
http://codeforces.com/contest/1332/problem/A
题意:
一个人处在一个给出的区间内,这个人可以向上下左右四个方向走。然后给出了这个人在每个方向上走的步数:(a,b,c,d)对应着(上,下,左,右)。问这个小人会不会走出给定的区域。
题解:
很明显,左右方向和上下方向分开考虑,互不影响。每个方向的步数可以相互抵消。比如左走一步,右走一步就回到原点。
注意:如果最终抵消为0且该方向上步数不是为0,也依然要判断在某个方向上是不是至少有1的长度,因为在抵消的过程中,小人一定是会动的,所以必须给他空间才能动。
AC代码:

#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl

using namespace std;

int a,b,c,d;
int x,x1,x2;
int f,f1,f2;

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		cin>>a>>b>>c>>d;
		cin>>x>>f>>x1>>f1>>x2>>f2;
		bool ok1=false;
		if(a>b)
		{
			int d1=a-b;
			int d2=x-x1;
			if(d2>=d1)
				ok1=true;
			if(max(a,b)>0&&(x2-x1)==0)
			{
				ok1=false;
			}
		}
		else
		{
			int d1=b-a;
			int d2=x2-x;
			if(d2>=d1)
				ok1=true;
			if(max(a,b)>0&&(x2-x1)==0)
			{
				ok1=false;
			}
		}
		bool ok2=false;
		if(c>d)
		{
			int d1=c-d;
			int d2=f-f1;
			if(d2>=d1)
				ok2=true;
			if(max(c,d)>0&&(f2-f1)==0)
			{
				ok2=false;
			}
		}
		else
		{
			int d1=d-c;
			int d2=f2-f;
			if(d2>=d1)
				ok2=true;
			if(max(c,d)>0&&(f2-f1)==0)
			{
				ok2=false;
			}
		}
		//cout<<ok1<<ok2<<endl;
		//DBEUG(ok2);
		if(ok1&&ok2)
			cout<<"Yes\n";
		else
			cout<<"No\n";
	}
	return 0;
}

B.Composite Coloring
原题链接:
http://codeforces.com/contest/1332/problem/B
题意:
给你一个数组,数组中每个元素小于1000且都是复数。
现在你有11种颜色,你可以从其中挑选m种颜色(m>=1&&m<=11)去给每个元素进行涂色。要求涂同一种颜色的所有元素两两之间的最小公因数大于1.给出合理的方案。
题解:
数组元素小于1000,可给的颜色又有11种,而平方小于1000的质数有11个。很容易就想到以每一个质数涂色依据,将数组中的元素按照最小非1的因数去归类。然后按照每一类去统一涂色即可。
为什么平方小于1000就可以?
因为A>B方,A的最小非1因数才有可能是比B大的。
AC代码:

#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl

using namespace std;
#define LL long long

const int maxn=1e3+5;
int a[10005];
int n;
int prime[11]={2,3,5,7,11,13,17,19,23,29,31};
int ans[1005];
int out[1005];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n;
		MS0(ans);
		bool vis[1005];
		MSf(vis);
		int cnt=1;
		for(int i=0;i<n;i++)
		{
			cin>>a[i];
			for(int j=0;j<11;j++)
			{
				if(a[i]%prime[j]==0)
				{
					if(!vis[prime[j]])
						cnt++;
					vis[prime[j]]=true;
					break;
				}
			}
		}
		int tmp=1;
		for(int j=0;j<11;j++)
		{
			if(vis[prime[j]])
			{
				ans[prime[j]]=tmp++;
			}
		}
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<11;j++)
			{
				if(vis[prime[j]])
				{
					if(a[i]%prime[j]==0)
					{
						out[i]=ans[prime[j]];
						break;
					}
				}
			}
		}
		cout<<cnt-1<<"\n";
		for(int i=0;i<n;i++)
		{
			cout<<out[i]<<" ";
		}
		cout<<"\n";
	}
	return 0;
}

C.K-Complete Word
原题链接:
http://codeforces.com/contest/1332/problem/C
题意:
给你一个字符串,想让他变成一个回文串(s[i]=s[n+1-i]),且具有周期K(s[i]=s[i+k])。你每次操作可以改变字符串中某个字符,问最少改变多少次。
题解:
由回文串和周期可以推出s[n-k+i]=s[n+1-i],可以发现每一个周期内也是回文串。之后遍历一个周期内s[i] (i>=1&&i<=k) 以其他周期内对应同位置的字符 分别为26个拉丁字母需要改变多少次即可。
AC代码:

#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl

using namespace std;
#define LL long long

const int maxn=2e5+5;

int num[maxn][30];

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		int n,k;
		string s;
		cin>>n>>k;
		cin>>s;
		for(int i=1;i<=k;i++)
		{
			for(int j=0;j<26;j++)
				num[i][j]=0;
			for(int j=0;j<n/k;j++)
			{
				int now=i+j*k-1;
				int tmp=s[now]-'a';
				num[i][tmp]++;//记录每个位置每一个字符出现的次数
			}
		}
		int ans=0;
		for(int i=1;i<=(k+1)/2;i++)
		{
			int msum=5*maxn;
			for(int j=0;j<26;j++)
			{
				if(k-i+1==i)//奇回文串
				{
					if(msum>(n/k-num[i][j]))
					{
						msum=n/k-num[i][j];
					}
				}
				else if(msum>(2*n/k-num[i][j]-num[k-i+1][j]))
				{
					msum=2*n/k-num[i][j]-num[k-i+1][j];
				}
			}
			ans+=msum;
		}
		cout<<ans<<"\n";
	}
	return 0;
}

D.Walk on Matrix
原题链接:
http://codeforces.com/contest/1332/problem/D
题意:
给出一个n*m矩阵(矩阵上的每个元素有自己的value),一个人初始处于(0,0),要走到(n,m),只能向右和向下走,请找到最长的路。最长的路是这样定义的:路径上所有的值按位与的值。
小明用了一种错误的dp方法,求解出来了答案x。而正确答案为m。现在已知m和x的差值k。请构造出一个矩阵使得小明算出来的答案与正确答案相差刚好为k。
题解:
小明错误以为局部最优解可以推向全局最优解。
通过样例可以发现,只需要构造两条路,一条正确的路,一条错误的路。在正确的路径上通过矩阵上的其他值去影响局部最优,诱导小明走错误的路即可。
例如以下2*3的矩阵:

217^k 217 0
k 217^k k

正确的路 :(0,0)->(0,1)->(1,1)->(1,2)
错误的路:(0,0)->(0,1)->(0,2)->(1,2)
你只需要构造无论怎么走小明按照错误的局优得到的结果都是0,同时又存在一条结果为k的最优路径即可。
给出一个表格

a b a^b (a^b)&b (a^b)&b&(a^b)
0 0 0 0 0
0 1 1 1 1
1 0 1 0 0
1 1 0 0 0

令a=217 b=k 就能够得到(0,0)->(1,0)-(1,1)的结果,发现这个结果取决于b(即k)。

a b a^b (a^b)&a (a^b)&a&(a^b)
0 0 0 0 0
0 1 1 0 0
1 0 1 1 1
1 1 0 0 0

令a=217 b=k 就能够得到(0,0)->(0,1)-(1,1)的结果,发现这个结果取决于a(即217)。
已知k<1e5<217,所以肯定走(0,0)->(1,0)->(1,1)时dp[1][1]为k,走(0,0)->(1,0)->(1,1)的dp[1][1]为2^17 。小明在选择的时候肯定会选择较大的217。然而217 & k的结果必然是0。至此,小明已经走上了不归路。
实际上最优路径是dp[1][1]dn等于k的路。最终最优路径的结果为k&k=k。
AC代码:

#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl

using namespace std;
#define LL long long
#define Rint register int
#define U unsigned
#define forn(i,a,b) for(int i = a;i <= b;++i)
#define nfor(i,a,b) for(int i = a;i >= b;--i)
#define pii pair<int ,int>
#define MS0(X) memset(X,0,sizeof(X))
#define MSf(X) memset(X,false,sizeof(X))
#define MS1(X) memset(X,-1,sizeof(X))
#define BR printf("--------------------\n")
#define pb push_back
#define rep(i,a,b) for(Rint i=a;i<=b;++i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
const double PI=atan(1.)*4.;
const int maxn=1e6+5;
const int inf = 0x3f3f3f3f;
const int mod=1e9+7;
const double e=2.71828182845904523536;
int dirx[8]={1,0,-1,0,1,-1,-1,1};
int diry[8]={0,1,0,-1,1,1,-1,-1};

int n,m;
int a[1005][1002];
int dp[1005][1005];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    /*
    //小明错误的dp
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
    }
    dp[1][1]=a[1][1];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            //dp[i+1][j]=max(dp[i+1][j],dp[i][j]&a[i+1][j]);
            //dp[i][j+1]=max(dp[i][j+1],dp[i][j]&a[i][j+1]);
            dp[i][j]=max(dp[i][j],max(dp[i-1][j]&a[i][j],dp[i][j-1]&a[i][j]));
            cout<<dp[i][j]<<" ";
        }
        cout<<endl;
    }
    cout<<dp[n][m];*/
    int k;
    cin>>k;
    int mx=(1<<17);
    cout<<2<<" "<<3<<"\n";
    int ans[2][3];
    ans[0][0]=mx^k;
    ans[0][1]=mx;
    ans[0][2]=0;
    ans[1][0]=k;
    ans[1][1]=mx^k;
    ans[1][2]=k;
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<3;j++)
        {
            cout<<ans[i][j]<<" "; 
        }
        cout<<"\n";
    }
    return 0;
}

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/105276832
今日推荐