2020-02-07 蓝桥杯模拟赛1 F&H

 

F. 试题F:你好,2020 15'

描述

2020年,这个年份很特别,2020从中间分成两个整数,大小形状完全一样。

wlxsq对形如2020的数字很感兴趣(不包括前导零),在11200中这样的数字包括11、22、3344、55、66、77、88、99、1010、1111,共11个,他们的和是2616

请问,在1n中,所有这样的数的和是多少?

输入

输入一行包含一个整数n

输出

输出一行,包含一个整数,表示满足条件的数的和。

样例

输入

1200

输出

2616

提示

【评测用例规模与约定】

对于20%的评测用例,1 ≤ n ≤ 100。

对于50%的评测用例,1 ≤ n ≤ 10^3。

对于80%的评测用例,1 ≤ n ≤ 10^4。

对于100%的评测用例,1 ≤ n ≤ 10^6。

 

 

//代码1
#include<stdio.h>
int main(){
    long i,n,sum;
    scanf("%d", &n);
    sum=0;
    for (i=1;i<=n;i++){
        if(10<=i&&i<100){
            if(i/10==i%10) sum+=i;
        }
        if(1000<=i&&i<10000){
            if(i/100==i%100) sum+=i;
        }
        if(100000<=i&&i<1000000){
            if(i/1000==i%1000) sum+=i;
        }
    }
    printf("%d",sum);
    return 0;
}
//代码2
#include<stdio.h>
using namespace std;
#include<iostream>
#define debug(x) cerr<<#x<<" "<<x<<endl;
int n,A,B,a[20],p10[20]={1,10,100,1000,10000,100000,1000000};
int split(int x){
    int cnt=0,res=0;
    for(;x;x/=10) a[++cnt]=x%10;
    int cct=cnt+1>>1;
    if(cnt&1){
        for(int i=cnt/2;i;i--) res=res*10+9;
        return res;
    }
    for(int i=cnt;i>cct;i--) A=A*10+a[i];
    for(int i=cct;i;i--) B=B*10+a[i];
    if(A<=B) return A;else return A-1;
}
int deal(int x){
    int cnt=0,t=x;
    for(;x;x/=10) a[++cnt]=x%10;
    return t*p10[cnt]+t;
}
long long ans;
int main(){
    cin>>n;
    int sz=split(n);
    for(int i=1;i<=sz;i++) ans+=deal(i);
    cout<<ans;
    return 0;
}

 

H. 试题H:计算器 22'

描述

我们知道,windows自带calc功能。

wlxsq决定制作一个Calc,该Calc具备求解一元一次方程的功能。

为了简化工作,拒绝花里胡哨。这个方程中,只有一个等号"=",零个或多个加号"+"、减号"-",一种小写字母表示未知数。当然,减号也可是负号

方程中并没有括号,也没有除号,方程中的字母表示未知数。

输入

仅一行,表示一个合法的方程,包含“+”、“-”、“=”、数字及小写字母。

输出

仅一行,表示答案,形式为“未知元=答案”。对答案保留3位小数,保证答案的绝对值不超过10000。

样例

输入

2a=1

输出

a=0.500

输入

-5+2x=-10

输出

x=-2.500

提示

【评测用例规模与约定】

对于20%的数据,输入数据没有"+,-"符号

对于100%数据,长度不超过255,数字不超过10000,保证只出现一种小写字母。

 

//代码1 
#include<stdio.h>
#include<string.h>
#include<sstream>
#include<iostream>
using namespace std;
#define debug(x) cerr<<#x<<" "<<x<<endl;
string s,A,B;int a[5];char wz;bool cf;
int getc(string &str,int len){
    for(int i=0;i<len;i++) if(isalpha(str[i])) return str[i];
    return -1;
}
void del(string &str,int l,int r){
    int i;
    for(i=r-1;i>=l;i--) if(!isdigit(str[i])) break;
    int num=0,f=1;
    if(i>=0){
        if(str[i]=='-') f=-1;else if(isdigit(str[i])) num=str[i]-'0';
    }
    for(int j=i+1;j<r;j++) num=num*10+str[j]-'0';
    if(!num&&(!r||!isdigit(str[r-1]))) num=1;
    num*=f;
    a[1]+=num;
    int li=i<0?0:i; int sz=r-li+1;
    str.erase(li,sz);
}
bool read(char *&s,int &x){
    bool f=0;x=0;
    for(;*s<'0'||*s>'9';*s++) if(*s=='-') f=1;
    for(;*s>='0'&&*s<='9';*s++) x=(x<<3)+(x<<1)+*s-'0';
    if(f) x=-x;
    if(*s) return 1;else return 0;
}
void deal(string &str){
    int len=str.length();
    int zm=getc(str,len);if(~zm) if(!cf) wz=zm,cf=1;
    int now=0;
    for(int nx=-1;;){
        if(str.find(zm,now)==string::npos) break;
        nx=str.find(zm,now);
        del(str,now,nx);
    }
    len=str.length();
    if(len<1) return ;
    char *snum=(char *)malloc((len+1)*sizeof(char));
    for(int i=0;i<len;i++) snum[i]=str[i];snum[len]=0;
    bool flag=1;
    for(int x;flag;) flag=read(snum,x),a[2]+=x;
//    delete snum;
}
int main(){
    getline(cin,s);stringstream sio(s);
    getline(sio,A,'=');getline(sio,B);
    deal(A);
    a[1]=-a[1];a[2]=-a[2];
    deal(B);
    printf("%c=%.3lf\n",wz,-(double(a[2])/double(a[1])));
    return 0;
}
/*
hack data:
input
2+0x-1x=0x-x-2x
output
x=-1.000
*/
 1 def solve(eq,var='x'):
 2     eq1 = eq.replace("=","-(")  +  ")"
 3     eq1 = eq1.replace("x","*x")
 4     eq1 = eq1.replace("+*x","+x")
 5     eq1 = eq1.replace("-*x","-x")
 6     eq1 = eq1.replace("(*x","(x")
 7     if eq1[0] == '*':
 8         eq1 = eq1[1:]
 9     c = eval(eq1,{var:1j})
10     #将x = 1j代入算式,结果是-9708+3j
11     if c.real!=0:
12         return -c.real/c.imag
13     else:
14         return 0
15 test = input()
16 ch = 'x'
17 for i in range(len(test)):
18     if ord('a') <= ord(test[i]) <= ord('z'):
19         ch = test[i]
20         test = test.replace(test[i],'x')
21         break
22 print("%s=%.3lf"%(ch,solve(test)))

 

附 全套题解

 

A:战疫情 5'

直接枚举x,枚举y,判断x+y是否满足在区间[20000, 21000]范围内,且2*x + 100y是否刚好等于50000,如果是,则统计答案即可。

这道题目是 题库P1047百钱买鸡 的弱化版~

当然,手算也是很香的~

x + y = 20000, 2x + 100y = 50000 可以求出一个x,y

x + y = 21000, 2x + 100y = 50000 也可以求出一个x,y

很明显,方案中y的个数是连续的。

答案: 21

B:行动 5'

这个题目手算很简单!总共2020步,每4步一圈,每一圈横坐标-2,纵坐标+2。刚好505圈.

当然这个题目也可以用循环,循环2020次。

在第i次循环,

如果i\%4=1,则x+i,

如果i\%4=2,则y-i,

如果i\%4=3,则x-i,

如果i\%4=4,则y+i,

答案:-1010\ 1010

C:莱布尼茨公式 10'

直接一个for循环枚举累加即可。

注意了,C/C++选手,请使用 double!请使用 double!请使用 double!

这次很多同学就是使用float导致精度误差,答案错误!double能够精确到15位小数左右

答案:3.141098

D:价值之和 10'

质数:指在 大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

质因子:能整除给定正整数的 质数

写一个函数function1

判断一个数的每一位是否包含数字5,

x \% 10 == 5 判断, 然后再去掉最后一位

再写一个函数function2:

对于一个给定的数x,判断起质因子的个数。

直接枚举2x-1,判断是否是质数,是否是x的因子,如果是,则计数+1

这是P1020,P1044 两题的结合

答案:3257

E:数方 15'

很有意思的一道题。比较简单。

这个题目可以手算结合编程求答案。从三位数的四次方数作为出发点,逐个确定。当然,在判断质数,三角数的时候计算量比较大,可以借助计算机,编程快速计算。

当然这个题目,编程写,有趣的很。

9for循环嵌套,枚举每一个数字,9个数字填好之后,再判断是否满足6个条件,如果满足,则就是答案。

当然,如果不加优化,需要等电脑跑一会就是了~

答案:7\ 2\ 9\ 4\ 5\ 7\ 1\ 6\ 9

F:你好,2020 15'

第一道编程大题~

根据数据范围,所以数字要么是2位数,要么是4位数,要么是6位数.

如果i6位数.则判断i\%1000是否等于[\frac{i}{1000}],等于则满足条件。

2位数,4位数的同理

G:最优值 18'

这是一道贪心题

Value的计算和单词长度,首字符,以及单词再排列中的位置有关。

单词长度固定的,首字符也是固定的,可以先计算出来。再根据|ch| * len 的值,越大的则在排列中的位置越靠后,让ID尽可能大。

Java,C/C++选手注意了,这个题目,int型变量是肯定存不下的~

H:计算器 22'

这是一道模拟题~

对于读入的字符串分割。从左到右,按照符号分割。

统计出一个常数的和x,再统计出一个未知数的系数和y。最后x / y即可。

I:对称迷宫 25'

这个题目,最暴力的做法就是直接dfs,会搜索的同学,40\%的分应该要拿到。

就是从左上角(1,1)出发,dfs,找出所有到(n, n)的路径,保存并去重,统计对称路径,计算出来的就是答案。但是只能过40\%的数据~

时间复杂度为卡特兰数,感兴趣的可以研究一下。

对于n<=18,做两遍dfs.

第一遍dfs(1,1)开始搜索到中点(x+y=1)出,并将路径保存到路径1方案中。

然后再从(n,n)跑到中点,保存路径2

最后枚举路径1中的路径是否在路径2中出现,且中点一样。

J:因数个数 25'

这个题目,对于40\%的数据,还是比较好拿的。

对于60\%的数据,需要对质数筛法有一定的了解。

对于100\%则是考察的线性筛+桶排序,以及对数据的敏感度。

1、对于20\%的数据。

枚举2n中的每一个数,然后逐一求出每一个数的因数个数。对因数个数排序,找出第k小的数字即可。

时间复杂度O(n^2)

2、对于40\%的数据,优化一下即可。

在逐一求每一个数的因数时枚举到\sqrt{n}即可。

时间复杂度O(n\sqrt{n})

3、对于60\%的数据

使用质数筛法的原理,枚举2n,对于每一个数i,将其倍数都标记+1,表示有i这么一个因数。

然后对每一个数的因数个数进行排序,求出第k小即可。

时间复杂度O(nlogn)

4、对于100\%的数据

考虑线性筛算出 2N 的因数个数。d[n] 表示 n 的约数个数。

n=p_1^{a1}*p_2^{a2}…p_k^{ak} , d[n]=(a_1+1)(a_2+1)...(a_k+1)。

p[i]表示第 i 个质数,Min[i]表示 i 的最小质因子出现次数 + 1

1. 当前数i是质数,d[i]=2,Min[i]=1

2. 线筛过程中,若 i\%p[j]!=0, 则 i 不存在约数 p[j],d[p[j] * i] = 2 * d[i], Min[p[j]*i] = 1

3. 否则,p[j]i 的最小质因子, Min[p[j] * i] = Min[i] + 1。d[p[j] * i] = \frac{d[i] * Min[p[j] * i]}{(Min[i] + 1)}

最后对d数组桶排序找出第 k 小,时间复杂度 O(N)

对于N >= 2 * 10^7,质数的个数已经大于k了,所以直接特判就好了~

 

posted @ 2020-02-11 11:24  神犇(shenben)  阅读(844)  评论(0编辑  收藏  举报