Codeforces Round #524 (Div. 2) A(水) B(水规律) C(模拟)D(规律)

A. Petya and Origami

题目链接:http://codeforces.com/contest/1080/problem/A

题目大意:做一个邀请函,需要2红+5绿+8蓝色的纸张,一个本子有k张纸(同一种颜色),问要发出n张邀请函最少需要多少个本子?

思路:直接对应的相除再相加就行了,水

AC:

int n,k;


int main()
{
	std::ios::sync_with_stdio(false);
	double n,k;
	while(cin>>n>>k)
	{
		cout<<(ll)(ceil((n*2)/k)+ceil((n*5)/k)+ceil((n*8)/k))<<endl;
	}
}

B. Margarite and the best present

题目链接:http://codeforces.com/contest/1080/problem/B

题目大意:一个数组,它的元素与下标的关系是ai=i*(-1)^i;然后求[l,r]区间的和

思路:相邻相加差1,直接判断即可

AC:

int n,k;


int main()
{
	std::ios::sync_with_stdio(false);
	int q;
	while(cin>>q)
	{
		while(q--)
		{
			int l,r;
			cin>>l>>r;
			if(l%2&&r%2)
				cout<<-r+(r-l)/2<<endl;
			else if(l%2&&r%2==0)
				cout<<(r-l+1)/2<<endl;
			else if(l%2==0&&r%2)
				cout<<-(r-l+1)/2<<endl;
			else
				cout<<r-(r-l)/2<<endl;
		}
	}
}

C. Masha and two friends

题目链接:http://codeforces.com/contest/1080/problem/C

题目大意:给出一个马赛克图形,相邻的格子是不同的颜色,然后起点1,1处是白色,染两次色,第一次把一个方块全染成白色,第二次全染成黑色,问最后白色和黑色方块分别有多少个

思路:模拟,判断一下染色的个数,然后交叉染色,最后判断一下染色的区间有没有叠加,就是模拟比较麻烦...

AC:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
  
#include<stdio.h>
#include<string.h> 
#include<math.h> 
   
//#include<map>  
//#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
  
#define ll long long 
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e4+10;
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
struct Edge{
	int v,w,nxt;
	Edge(int _v=0,int _w=0,int _nxt=0):
	v(_v),w(_w),nxt(_nxt){}
}edge[MAXN<<1];
int head[MAXN],ecnt;
void intt()
{
	clean(head,-1);
	ecnt=0;
}
void add(int u,int v,int w)
{
	edge[ecnt]=Edge(v,w,head[u]);
	head[u]=ecnt++;
}
//-------------------------

ll n,m;

int main()
{
	std::ios::sync_with_stdio(false);
	int T;
	while(cin>>T)
	{
		while(T--)
		{
			//cout<<"--------"<<endl;
			cin>>n>>m;
			ll sumw,sumb;
			//白色起点 
			if(n%2&&m%2)//白色多一个 
				sumw=(n*m)/2+1;
			else//黑白数量相等 
				sumw=(n*m)/2;
			sumb=(n*m)/2;
			//cout<<sumw<<" "<<sumb<<endl;
			ll x1,x2,y1,y2;
			cin>>x1>>y1>>x2>>y2;
			//染白 
			if(x1%2==y1%2)//起点是白色 
			{
				sumb-=((x2-x1+1)*(y2-y1+1))/2;
				sumw+=((x2-x1+1)*(y2-y1+1))/2;
			}
			else
			{
				if((x2-x1+1)%2&&(y2-y1+1)%2)//黑色的多一个 
				{
					sumb-=((x2-x1+1)*(y2-y1+1))/2+1;
					sumw+=((x2-x1+1)*(y2-y1+1))/2+1;
				}
				else
				{
					sumb-=((x2-x1+1)*(y2-y1+1))/2;
					sumw+=((x2-x1+1)*(y2-y1+1))/2;
				}
			}
			//cout<<sumw<<" "<<sumb<<endl;
			ll a1,b1,a2,b2;
			cin>>a1>>b1>>a2>>b2;
			//染黑
			if(a1%2==b1%2)//起点是白色 
			{
				if((a2-a1+1)%2&&(b2-b1+1)%2)//白色的多一个 
				{
					sumb+=((a2-a1+1)*(b2-b1+1))/2+1;
					sumw-=((a2-a1+1)*(b2-b1+1))/2+1;
				}
				else
				{
					sumb+=((a2-a1+1)*(b2-b1+1))/2;
					sumw-=((a2-a1+1)*(b2-b1+1))/2;
				}
			}
			else//起点是黑色 
			{
				sumb+=((a2-a1+1)*(b2-b1+1))/2;
				sumw-=((a2-a1+1)*(b2-b1+1))/2;
			}
			//cout<<sumw<<" "<<sumb<<endl;
			//交叉染完后 剩下的 比较一下 
			ll xx1=max(x1,a1),xx2=min(x2,a2),yy1=max(y1,b1),yy2=min(y2,b2);
			if(xx1<=xx2&&yy1<=yy2)//重叠区域染黑 
			{
				if(xx1%2==yy1%2)//起点是黑色(本来白色,染成染成黑色) 
				{
					sumb+=((xx2-xx1+1)*(yy2-yy1+1))/2;
					sumw-=((xx2-xx1+1)*(yy2-yy1+1))/2;
				}
				else//起点是白色(本来黑色,染成白色,没有染回黑色)
				{
					if(xx1==xx2&&yy1==yy2)
						sumb++,sumw--;
					else if((xx2-xx1+1)%2&&(yy2-yy1+1)%2)//白色的多一个 
					{
						sumb+=((xx2-xx1+1)*(yy2-yy1+1))/2+1;
						sumw-=((xx2-xx1+1)*(yy2-yy1+1))/2+1;
					}
					else
					{
						sumb+=((xx2-xx1+1)*(yy2-yy1+1))/2;
						sumw-=((xx2-xx1+1)*(yy2-yy1+1))/2;
					}
				}
			}
			cout<<sumw<<" "<<sumb<<endl;
		}
	}
}

D. Olya and magical square

题目链接:https://codeforces.com/contest/1080/problem/D

题目大意:给你一个2^n*2^n 的方块,每一次选一个正方形把他分成四块,一共k步问最后是否可以让最后的左下角方块的大小等于右上角方块的大小,而且可以从左下角沿着同样大小的方块走到右上角

思路:最后的路径一定可以是沿着边界走到右上角,只要路径上大小固定,就可以算出其它块可以分裂的次数,所以只要动态维护当前分裂次数a和可以分裂的次数b,如果当前分裂次数已经>k则不满足,否则如果出现a<=k&&a+b>=k说明有满足情况的答案。动态维护分裂的过程需要维护好多个变量,首先要维护路径的长度,这样也就知道去除路径剩多少个可分裂的块。还要维护左下角块的大小,也就知道可分裂次数。之后动态维护a,b就可以了。

AC:

#include<stdio.h>
#include<string.h> 
#include<math.h> 

#include<map>  
//#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
#define ll long long 
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=2e5+10;
const ll INF=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);

ll pathl(ll n,ll k)
{
    k--;
    ll pow2 = 4,cnt = 0;
    while(k>=pow2-1)
	{
        cnt++;
        k-=(pow2-1);
        pow2*=2;
    }
    return max(n-1-cnt,(ll)0);
}
int main()
{
    ll t,n,k;
    cin>>t;
    while(t--)
	{
        cin>>n>>k;
        if(n==2 && k==3)
        {
        	cout<<"NO"<<endl;
			continue ;
		}
        ll pow4=1,tmp1=k,tmp2=n;
        if(n<=35)
		{
            while(tmp2--)
			{
                tmp1-=pow4;
                pow4*=4;
            }
            if(tmp1>0)
			{
                cout<<"NO"<<endl;
				continue;
            }
            cout<<"YES "<<pathl(n,k)<<endl;
        }
		else
            cout<<"YES "<<pathl(n,k)<<endl;
    }
}


 

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/85008216