第二次CSP模测

第一题

HRZ的序列

给定一个序列a,判断是否存在一个数K,使得一些数加上K,一些数减去K,一些数不变,使得整个序列中所有的数相等。序列长度n<10^4, 数字|ai|<10^15。

Input

第一行为测试数据的组数n
接下来有n组数据,每一组数据第一行为m,表示接下来输入m个数

Output

输出"YES"或者“NO”

Example
  • input
    2
    5
    1 2 3 4 5
    5
    1 2 3 4 5
  • output
    NO
    NO

解题思路

这个题思路比较简单(菜鸡爆零。。。),只要满足下列条件中的一个即可:
1.所有数相同
2.只有两个不同的数
3.只有三个不同的数而且其中两个的和是第三个数的2倍

代码实现

#include<iostream>
using namespace std;

long long num[3],x;
long long flag,cnt,n;

int main()
{
    ios::sync_with_stdio(false);
    cin >> cnt;
    while(cnt--){
        cin >> n;
        for(long long i=0;i<n;i++){
            cin >> x;
            long long j=0;
            for(;j<flag&&j<3&&num[j]!=x;j++);
            if(j>=flag && flag<3) num[flag++]=x;
            else if(num[0]!=x&&num[1]!=x&&num[2]!=x) flag++;
        }
        if(flag==3){
            if(num[0]+num[2]==num[1]*2 || num[0]+num[1]==num[2]*2 || num[1]+num[2]==num[0]*2) ;
            else flag++;
        }
        if(flag<=3) cout << "YES" << endl;
        else cout << "NO" << endl;
        flag=0;
    }
    return 0;
}

第二题

HRZ学英语

给定一个字符串,其中包括26个大写字母和特殊字符’?’,’?'可以代表任何一个大写字母。现问是否存在一个位置连续的且由26个大写字母组成的子串,在这个子串中每个字母只出现一次。若存在,请输出从左侧算起的第一个出现的符合要求的子串,若有多组解同时符合位置最靠左,则输出字典序最小的那个解。若不存在,输出-1。

Input

一个字符串

Output

相应的字符串或者-1

Example
  • input1
    ABC??FGHIJK???OPQR?TUVWXY?
  • output1
    ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • input2
    AABCDEFGHIJKLMNOPQRSTUVW??M
  • output2
    -1

解题思路

从第25个字母开始遍历字符串, 开一个长度为26的数组来进行统计来判断数组中的26个字母各不相同,同时通过这个数组来找出 ‘?’ 对应的字母。然后将字符串中 ‘?’ 替换为指定的字母即可。若替换后得到的字符串中各不相同的字母数等于26, 就输出该字符串;找到末尾字符串仍然不符合要求输出-1.

代码实现

#include <iostream>
#include <string.h>
#include <string>
using namespace std;
int l, m, cnt,sum,r = 25,index=25;
int flag[26] = {0};
string s,res;
bool judge=0;

int main()
{
    ios::sync_with_stdio(false);
    res = "00000000000000000000000000";
    cin>>s;
    while(index<s.size())
	{
		m = 0;
		cnt = l+26;
        memset(flag, 0, sizeof(flag));
		for(int i=l;i<cnt;i++)
		{
			if(s[i]!='?')
			{
				res[i-l] = s[i];
				flag[s[i]-'A'] = 1;
			}

		}
		for(int i=l;i<cnt;i++)
		{
		 	if(s[i]=='?')
		 	{
		 		for(int j=0;j<26;j++)
		 			if(!flag[j])
		 			{
		 				res[i-l] = j + 'A', flag[j] = 1;
		 				break;
		 			}
		 	}
		 }
		l++;
		sum = 0;
		for(int i=0;i<26;i++)
			if(flag[i]==1)
				sum++;
		if(sum==26)
		{
            judge = 1;
            break;
        }
        index++;
    }
    if(judge) cout << res;
    else cout<<-1;
 	return 0;
}

第三题

咕咕东的奇妙序列

112123123412345 …这个序列由连续正整数组成的若干部分构成,其中第一部分包含1至1之间的所有数字,第二部分包含1至2之间的所有数字,第三部分包含1至3之间的所有数字,第i部分总是包含1至i之间的所有数字,11212312341234512345612345671234567812345678912345678910,其中第1项是1,第3项是2,第20项是5,第38项是2,第56项是0。现在想知道第 k 项数字是多少。

Input

第一行是测试数据的组数n,接下来会有n组测试数据,每组会输入一个数字,要求出序列里对应的数字

Output

输出序列对应数字

Example
  • input
    5
    1
    3
    20
    38
    56
  • output
    1
    2
    5
    2
    0

解题思路

这个题乍一看很简单,当发现第56个数字为0的时候觉得不对劲。。。
然后发现每小部分是等差数列:
1 1
12 2
123 3
(差为1)
12345678910
1234567891011
123456789101112
(差为2)
每大部分分别讨论:1-9(10-1)、10-99((10-1)*10)、100-999((10-1)1010)
然后再使用二分搜索数字,找到res,前res部分总位数小于或等于k,求出前res部分总位数,第res+1部分第(k减去前res部分总位数)位就为答案。

代码实现

#include<iostream>
using namespace std;

int q;
long long k;

long long get_index(long long val) {
    long long e = 1, s = 1, d = 0, n = 0, index = 0;//start end
    while (true) {
        n = 9 * e;
        e *=10;//每一段的结尾数字
		d++;//等差数列的差
		if (val < e) {
			n = val - e / 10+1;
			index += s * n + n * (n - 1)*d / 2;
			break;
		}
        index += s * n + n * (n - 1)*d / 2;//等差数列公式
		s += (n - 1)*d + d + 1;
	}
	return index;
}

int main() {
	cin >> q;
	while (q--) {
		cin >> k;
        int l = 0, r = 1e9, mid = 0, index;
	    while (r>=l) {
		    mid = (l + r) / 2;
		    long long res = get_index(mid);
		    if (res >= k) r = mid - 1;
            else
            {
			    index = mid;
			    l = mid + 1;
		    }
	    }
		k = k - get_index(index);
		long long e = 1,  d = 0, n = 0, res = 0,pos=0;
	    while (k) {
			n = 9 * e;
			e *= 10;
		    d++;
		    if (k <= n*d)
            {
                res += k / d;
			    pos = k % d;
			    break;
            }
			res += n;
		    k -= n * d;
	    }
	    if (pos == 0) cout << res % 10 << endl;
	    else {
            res++;
            for (; d != pos;d--) res /= 10;
            cout << res % 10 << endl;
	    }
	}
	return 0;
}

赛后总结

这次直接爆零。。。裂开,第一题是细节思考不到位,然后导致re,第二题情况考虑没全面导致wa,第三题。。开始不会做,后来思考后把代码敲了出来
第二题因为用了index与编译器关键字冲突导致ce(我傻了),第三题se(少见的运气)
CSP好难呀
tcl。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值