目录
7-1 Excel地址
7-2 分巧克力
7-4 日期问题
7-9 k倍区间
7-10 正则问题
——第八届蓝桥省赛-C组 (60 分)
Excel 单元格的地址表示很有趣,它使用字母来表示列号。
比如,A 表示第 1 列,B 表示第 2 列,Z 表示第 26 列,AA 表示第 27 列,AB 表示第 28 列,BA 表示第 53 列 ....
当然 Excel 的最大列号是有限度的,所以转换起来不难。
如果我们想把这种表示法一般化,可以把很大的数字转换为很长的字母序列呢?
本题要求对输入的数字,输出其对应的 Excel 地址表示方式。
输入格式:
一个正整数。输入的整数范围 [1,2147483647]。
输出格式:
一个字母序列,表示输入数字对应的 Excel 地址表示方式。
输入样例:
2054
输出样例:
BZZ
思路L:进制转换,26进制,满26,不进,转化为z
题解代码如下:
#include
using namespace std;
const int N = 1000;
int main()
{
int n;
cin >> n ;
int a=n, b, i=0;
char q[N];
while( a>26 )
{
b = a%26;
a /= 26;
if(b==0)
{
a -= 1;
b += 26;
q[i++] = 'A' + b -1;
}
else q[i++] = 'A' + b -1;
}
q[i++] = 'A' + a -1;
for(int j=i-1; j >= 0; j--) cout << q[j] ;
return 0;
}
——第八届蓝桥省赛-AB组 (80 分)
儿童节那天有 K 位小朋友到小明家做客。
小明拿出了珍藏的巧克力招待小朋友们。
小明一共有 N 块巧克力,其中第 i 块是 Hi×Wi 的方格组成的长方形。
为了公平起见,小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。
切出的巧克力需要满足:
例如一块 6×5 的巧克力可以切出 6 块 2×2 的巧克力或者 2 块 3×3 的巧克力。
当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?
输入格式:
第一行包含两个整数 N 和 K。
以下 N 行每行包含两个整数 Hi 和 Wi。
输入保证每位小朋友至少能获得一块 1×1 的巧克力。 1≤ N,K ≤10^5 , 1≤ Hi, Wi≤ 10^5
输出格式:
输出切出的正方形巧克力最大可能的边长。
输入样例:
在这里给出一组输入。例如:
2 10
6 5
5 6
输出样例:
在这里给出相应的输出。例如:
2
思路:二分查找
题解代码如下:
#include
#include
using namespace std;
const int N = 1e5+10;
int n, k;
int res;
int h[N],w[N];
bool check(int x)
{
int num=0;
for( int i = 1; i <= n; i++ )
num += (h[i]/x)*(w[i]/x);
if(num>=k) return true;
else return false;
}
int main()
{
cin >> n >> k;
for( int i = 1; i <= n; i++ )
scanf("%d%d",&h[i],&w[i]);
int l = 1, r = 1e5;
while( l < r )
{
int mid = l + r + 1>> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
res = l;
cout << res << endl;
return 0;
}
——第八届蓝桥省赛-B组 (70 分)
小明正在整理一批历史文献。这些历史文献中出现了很多日期。
小明知道这些日期都在1960年1月1日至2059年12月31日。
令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。
更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。
比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。
给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?
输入格式:
一个日期,格式是”AA/BB/CC”。
即每个’/’隔开的部分由两个 0-9 之间的数字(不一定相同)组成。
0≤A,B,C≤9
输出格式:
输出若干个不相同的日期,每个日期一行,格式是”yyyy-MM-dd”。
多个日期按从早到晚排列。
输入样例:
02/03/04
输出样例:
2002-03-04
2004-02-03
2004-03-02
思路:枚举
代码如下:
#include
#include
using namespace std;
int mon[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int year,month,day;
bool isyear(int &year)
{
if( year%400==0 || ( year%100!=0 && year%4==0 ) )
return true;
return false;
}
bool check_num(int &k )
{
year = k/10000;
month = (k%10000)/100;
day = k%100;
if( day < 1 || day > 31 )
return false;
if(month<1||month>12)
return false;
if( month!=2 )
{
if(day>mon[month])
return false;
}
else
{
if(isyear(year))
{
if(day>mon[month]+1)
return false;
}
else
{
if(day>mon[month])
return false;
}
}
return true;
}
int main()
{
int i = 19600101;
int j = 20591231;
int k, a, b, c;
scanf("%d/%d/%d",&a,&b,&c);
for( k = i; k <= j; k++)
{
if(check_num(k))
if((year%100==a&&month==b&&day==c)||(month==a&&day==b&&year%100==c)||(day==a&&month==b&&year%100==c)||(month==a&&day==b&&year%100==c))
printf("%d-%02d-%02d\n",year,month,day);
}
return 0;
}
——第八届蓝桥省赛-B组 (70 分)
给定一个长度为 N 的数列,A1,A2,…AN,如果其中一段连续的子序列 Ai,Ai+1,…Aj 之和是 K 的倍数,我们就称这个区间 [i,j] 是 K 倍区间。
你能求出数列中总共有多少个 K 倍区间吗?
输入格式:
第一行包含两个整数 N 和 K。
以下 N 行每行包含一个整数 Ai。
1≤N,K≤100000 , 1≤Ai≤100000
输出格式:
输出一个整数,代表 K 倍区间的数目。
输入样例:
5 2
1
2
3
4
5
输出样例:
在这里给出相应的输出。例如:
6
思路:前缀和哈希
代码如下:
#include
#include
#include
using namespace std;
const int N = 100010;
long long s[N];
int res[N];
int a[N];
int n,k;
int main()
{
long long cnt = 0;
cin >> n >> k;
for( int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
s[i] = (s[i-1] + a[i])%k;
//若前缀和相同,则区间和为零,则s[i]是K倍区间
cnt += res[s[i]];
res[s[i]]++;
}
cout << cnt + res[0] << endl ;
return 0;
}
——蓝桥第八届省赛-A组 (80 分)
考虑一种简单的正则表达式:
只由 x ( ) | 组成的正则表达式。
小明想求出这个正则表达式能接受的最长字符串的长度。
例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是: xxxxxx,长度是6。
输入格式:
一个由x()|组成的正则表达式。输入长度不超过100,保证合法。
输出格式:
输出所给正则表达式能接受的最长字符串的长度。
输入样例:
在这里给出一组输入。例如:
((xx|xxx)x|(x|xx))xx
输出样例:
在这里给出相应的输出。例如:
6
思路:暴力dfs
代码如下:
#include
#include
#include
using namespace std;
int k;
int n;
string s;
int dfs()
{
int res=0;
while(k> s;
n = dfs();
cout << n;
return 0;
}