Educational Codeforces Round 50 (Rated for Div. 2)

solved(A\B\D)

链接:http://codeforces.com/contest/1036

目录

A. Function Height

B. Diagonal Walking v.2

题目

题解 

代码

D. Vasya and Arrays

题目

题解

代码

C. Classy Numbers

题目

题解

代码



A. Function Height

  水题,略。


B. Diagonal Walking v.2

题目

  从原点出发,每次行动可向八个方向走。现在认为 diagonal moves 为斜着走的一步, 给定终点(n,m),要求正好走k步,使得斜着走的步数尽量多,问最多能写着走多少步。

  要求:O(1)解法。

题解 

  首先,如果n>m,那么交换n和m,保证n<m;

  然后,我们先走斜线到达(n,n)点,然后问题便转化成了 从(n,n)点正好走(k-n)步,到达(n,m)点。而这两点是在一条直线上的,所以可以通过分奇偶找规律来完成。

  (这题卡了很久)

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cmath>
using namespace std;

#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
#define next next_
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x7fffffff;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
const int N = 105;

inline void read(int &x) {
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}

inline void print(int x) {
    if(x<0){ putchar('-'); x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

/*inline void caltime(int tt) {
	tt = clock() - tt;
    cerr << (double)tt/CLOCKS_PER_SEC << " seconds!" << endl;
}*/

inline void print_matrix(int a[N][N],int n,int m,bool flag=0) {
	if(flag) {
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=m;j++)
				cout<<a[i][j]<<" ";
			cout<<endl;
		}
	}else {
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++)
				cout<<a[i][j]<<" ";
			cout<<endl;
		}
	}
}

inline void print_line(int *a,int n,bool flag=0) {
	if(flag) {
		for(int i=1;i<=n;i++)
			cout<<a[i]<<" ";
	}else {
		for(int i=0;i<n;i++)
			cout<<a[i]<<" ";
	}
	cout<<endl;
}

ll solve(ll n,ll m,ll k) {
	if(n>m)	swap(n,m);
	if(m>k)	return -1;
	ll ans = n;
	ll x = n,y = n;
	ll res = k-n;
	ll temp = m-n;
	if(res<temp)	return -1;
	if(temp==0) {
		if(res==1) {
			ans--;
			return ans;
		}
		if(res&1) ans += res-2;
		else ans += res;
		return ans;
	}
	if(temp&1) {
		ans += res-1;
	}else {
		if(res&1) {
			ans += res-2;
		}else {
			ans += res;
		}
	}
	return ans;	
}

ll q,n,m,k;

int main()
{
	cin>>q;
	while(q--) {
		scanf("%lld%lld%lld",&n,&m,&k);
		ll ans = solve(n,m,k);
		cout<<ans<<endl;
	}
	return 0;
}

D. Vasya and Arrays

题目

  给定长度为n的序列a和长度为m的序列b。可以对任意一个序列进行如下操作:用a[l]...a[r]的和去替换掉a[l]...a[r]。

  问至少操作多少次,能让a和b相等。否则输出-1.

题解

  这题比B题感觉容易不少,A的也很快(最后2分钟a掉了)。

       用两个指针分别只向a和b,相应的进行求和,如果suma>sumb,就让j往右移一个,依次类推。

代码


ll n,m,a[maxn],b[maxn];

int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
		scanf("%lld",&a[i]);
	cin>>m;
	for(int i=0;i<m;i++)
		scanf("%lld",&b[i]);
	int i=0,j=0;
	ll sum1 = a[0],sum2 = b[0];
	int last = 0;
	ll ans = 0;
	while(i<n&&j<m) {
//		cout<<sum1<<" "<<sum2<<endl;
		if(sum1==sum2) {
			sum1 = sum2 = 0;
			ans += i-last;
			last = i+1;
			i++;
			j++;
			sum1 = a[i];
			sum2 = b[j];
		}
		else if(sum1<sum2){
			i++;
			sum1+=a[i];
		}
		else if(sum1>sum2){
			j++;
			sum2 += b[j];
		}
	}
	if(sum1!=sum2)	cout<<-1<<endl;
	else	cout<<n-ans<<endl;
	return 0;
}

C. Classy Numbers

题目

  给T组询问,每组询问有L和R两个数,要求[L,R]区间中有多少个数字满足条件。

  条件:数字中最多含有3个非0数。比如1230,200,340等等,而12345则不符合条件。

        L,R<=1e18

题解

  由于区间过大,不可能枚举。所以我们可以先把所有符合要求的数求出来(约70万个),然后用二分查找的方法来确定具体个数。

代码

​

int t;
ll l,r;
vector<ll> e;
 
void solve(int pos,ll cnt,ll cur) {
	if(pos==18)	{e.push_back(cur); return;} 
	solve(pos+1,cnt,cur*10); //当前位为0,继续往后推
	if(cnt<3) { //非0数不满3个的情况
		for(int i=1;i<=9;i++)
			solve(pos+1,cnt+1,cur*10+i);
	}
}

int main()
{
	solve(0,0,0);
	e.push_back(1e18);
	cin>>t;
	while(t--) {
		scanf("%lld%lld",&l,&r);
		ll ans = upper_bound(e.begin(),e.end(),r)-lower_bound(e.begin(),e.end(),l); //二分查找,如果前面一个也用lower_bound的话,要分是否正好能找到这个情况来讨论
		cout<<ans<<endl;
	}
	return 0;
}

[点击并拖拽以移动]
​

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

总想玩世不恭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值