Codeforces Round #719 (Div. 3)

这毕竟是一场div3,这就是我的专场,但是自己的能力还是有限,怎么一会会就睡觉去了,对晚上的网卡得很,交了c题,一直没出结果,我就去睡觉了
前三道题目简单解释一下:

A. Do Not Be Distracted!

https://codeforces.ml/contest/1520/problem/A
就是先把字符串读进来,然后取出相邻重复的,然后拿一个桶,逐个的添加进去,一旦出现某个字母的个数大于1.就说明NO

B. Ordinary Numbers

https://codeforces.ml/contest/1520/problem/B
这道题目就是让你判断小于等于n的数字中,由同一个数字组成的数的个数,例如11 222 3333,这道题目这样做
如果只有一位数字,那么结果就是sum=n
如果有多位,先算出有多少位cnt,sum = sum + 9*(cnt-1);,因为每增加一位数,就会有从1到9个数字出现
在把目光放在第一个数字上,比如23154
上面我们已经把小于20000的所有算过了,就只剩下存不存在11111,22222的问题了,取出第一个数字构造22222,在判断22222<23154所以sum加上2个,否则加1个

代码展示

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

int a[15];
int b[15];
int cnt;
int weishu(ll n)
{
	int cnt = 0;
	while(n)
	{
		a[cnt] = n%10;
		n/=10;
		cnt++;
	}
	
	return cnt;
}

ll get(int n,int weishu)
{
	ll ans = n;
	for(int i=1;i<=weishu;i++)
	{
		ans = ans*10 +n;
	}
	
	return ans;
}

ll houzhui1(int n,int pos)
{
	ll ans = 0;
	for(int i=pos;i<cnt;i++)
	{
		ans = ans*10 + b[i];
	}
	
	return ans;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		ll sum = 0;
		ll n;
		cin>>n;
	    cnt = weishu(n);
		if(cnt==1)//只有一位 
		{
			sum += n;
		}
		
		else{
			sum  = sum + 9*(cnt-1);

			int j = 0;
			for(int i = cnt-1;i>=0;i--,j++)
			{
				b[j] = a[i];
			}
			
//			cout<<"-------"<<endl;
//			for(int i=0;i<cnt;i++)
//			{
//				cout<<b[i]<<endl;
//			}cout<<"-------"<<endl;
			
//			
//				cout<<"sum"<<sum<<endl;
				ll num = get(b[0],cnt-1);
				ll houzhui = houzhui1(b[0],0);
//				cout<<"houzhui "<<houzhui<<"num  "<<num<<endl;
				if(houzhui >= num)
				{
					sum += b[0];
				}
				else{
					
					if(b[0]>=1)
						sum += (b[0]-1);
					else
						sum += 0;
				}
		} 
		cout<<sum<<endl;
	}
	
	return 0;
}

C. Not Adjacent Matrix

https://codeforces.ml/contest/1520/problem/C

题意理解

这道题的意思就是说要你构造一个从1到n^2的方阵,要求每个数字的上下左右的四个数字不能和他相差一;
我的答案是估摸着好像除了2比较特殊不能构造出以外,其余的都可以,理论支撑我给不出,其余的怎么构造呢?
首先从左上角开始向右下角填,然后从左边向上边斜着填,哎呀!说不清,直接上图在这里插入图片描述
多画几个就看出来了,就是填斜着的时候注意主对角线的位置跳过,然后行数+列数是一个定值哦(这是填的关键)

代码展示

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

int a[105][105];

int main() {
	int t;
	cin>>t;
	while(t--) {
		int n;
		cin>>n;
		if(n==2)
			cout<<"-1\n";
		else if(n==1)
			cout<<"1\n";
		else {
			
			for(int i=1; i<=n; i++) {
				for(int j=1; j<=n; j++) {
					a[i][j] = 0;
				}
			}
			//cout<<"-----\n";
			int i = 1,j = 1,cnt = 1;
			for(int k=1; k<=n; k++) {
				a[k][k] = cnt++;
			}

			for(int i=2;i<=n;i++)
			{
				int sum = i+1;
				for(int k=i;k>=1;k--)
				{
					if(a[k][sum-k] == 0)
					{
						a[k][sum-k] = cnt++;
					}
				}
			}
			
			for(int i=2;i<=n-1;i++)
			{
				int sum = n+i;
				for(int k=n;k>=i;k--)
				{
					if(a[k][sum-k]==0)
					{
						a[k][sum-k] = cnt++;
					}
				}
			}

			for(int i=1; i<=n; i++) {
				for(int j=1;j<n; j++) {
					cout<<a[i][j]<<" ";
				}
				cout<<a[i][n]<<endl;
			}
		}
	}
	return 0;
}

D. Same Differences

https://codeforces.ml/contest/1520/problem/D

题意解读

这道题的意思是,给你一个数列,让你求出(i,j) 的个数 i<j 并且aj−ai=j−i.
只需要稍稍动一下脑子,移项你就会发现奇迹,别一上去就暴力N^2,移项后你就发现,不就是统计a[i] - i相等的出现的个数嘛,这里更巧的是用了map更加高效

代码展示

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 202020;

ll t;
ll n;
ll a[N];
ll book[N];

int main()
{
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        map<int ,int >mp;
        ll ans = 0;
        mp.clear();
        for(int i=1;i<=n;i++)
        {
            if(mp.count(a[i] - i))
                ans += mp[a[i]-i];
            mp[a[i]-i] ++ ;

        }
        cout<<ans<<endl;
    }
    return 0;
}

E. Arranging The Sheep

https://codeforces.ml/contest/1520/problem/E

题意解读

这道题目的意思就是说,给你一个只含点和星号的字符串,每次可以移动星号一次问你最少移动多少次可以使得所有的星号在一起。
这里看的别人的博客,说的是可以证明,在给定的条件下,只要只要把两边的星号向中间靠拢,就可以使得移动的次数最小,至于理论知识,我也阐释不清楚,说的简单点,就是要把两侧的向最中间的靠拢就可以了,但是要注意的是,如果当前的星号和最中间的星号中间间隔了n个星号,你就可以少移动n不呀,因为这n个放在你的前面岂不是更加的快。画个图示意一下。
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;

int t,n;
char str[N];
int a[N],cnt;

int main()
{
    cin>>t;
    while(t--)
    {
        cnt = 0;
        cin>>n;
        cin>>str;
        for(int i=0;i<n;i++)
        {
            if(str[i] == '*')
                a[cnt++]  =i;//记录下每个*的位置
        }

        int k = a[cnt/2];//记录中间的那个*的坐标
        int mid = cnt/2;//记录一半有多少个,为了在后边移动的时候隔过去

        ll ans  = 0;
        for(int i= 0;i<cnt;i++)
        {
            int dest = k-mid + i;//实际需要移动到的位置
            ans += abs(a[i]-dest);
        }
        cout<<ans<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值