有道难题资格赛(1)
- 参与人数
- 4849
- 提交次数
- 25797
分数 名次
1000 1~239
700 ~265
...
400 ~ 450
编号 | 标题 | 分数 | 通过率 | 通过人数 | 提交次数 |
A | 另类的异或 | 150 | 29% | 3405 | 11947 |
B | 有道搜索框 | 300 | 13% | 1439 | 11065 |
C | 最大和子序列 | 550 | 10% | 274 | 2785 |
A:另类的异或
- 时间限制:
- 1000ms
- 内存限制:
- 131072kB
- 描述
- 对于普通的异或,其实是二进制的无进位的加法
这里我们定义一种另类的异或A op B, op是一个仅由^组成的字符串,如果op中包含n个^,那么A op B表示A和B之间进行n+1进制的无进位的加法。
下图展示了3 ^ 5 和 4 ^^ 5的计算过程
- 输入
- 第一行有一个正整数T, 表示下面共有T组测试数据。
接下来T行,每行有一组测试数据,是由空格隔开的三个部分组成:
A B C
A和C是两个十进制整数,B是一个字符串,由n个^组成
1 <= T <= 100, 0<=A,B<2^30, 1<=n<=1000 - 输出
- 每个测试数据输出一行,包含一个数字,即该数据的结果,用十进制表示。
- 样例输入
2
3 ^ 5
4 ^^ 5- 样例输出
6
代码
#include <stdio.h>
#include <string.h>
#include <memory.h>
//将数字从十进制转换到制定进制
//input:
//n: 要转换的数字(十进制)
//m: 要转换的进制
//output:
//a,l: 要求进制的数字,和位数,[0]为最低位
void split(int n, int m,int a[],int &l)
{
l=0;
for(;n;n/=m)
{
a[l++]=n%m;
}
}
void print(int a[],int l)
{
for(int i=0;i<l;i++)
printf("%d ",a[i]);
printf("\n");
}
//将指定进制的数字做xor运算
//input:
//a,n1,b,n2
//m
//output:
//c
int xor(int const a[],int n1, int const b[],int n2, int m, int c[])
{
int k=n1>n2?n1:n2;
for(int i=0;i<k;i++)
{
c[i]=(a[i]+b[i])%m;
}
return k;
}
int A[50];
int nA=0;
int nB=0;
int B[50];
int nC=0;
int C[50];
//将数字从指定进制转换到十进制
int merge(int const a[],int n1, int m)
{
int r=0;
for(int i=0;i<n1;i++)
{
r =r*m+a[n1-1-i];
}
return r;
}
int main(int argc, char *argv[])
{
int T;
scanf("%d",&T);
while(T--)
{
int a,b=0,m;
char s[1000+1];
scanf("%d %s %d",&a,s,&b);
m=strlen(s)+1;
//printf("a %d b %d m %d\n",a,b,m);
memset(A,0,sizeof(A));
memset(B,0,sizeof(B));
memset(C,0,sizeof(C));
split(a,m,A,nA);
split(b,m,B,nB);
//print(A,nA);
//print(B,nB);
nC=xor(A,nA,B,nB,m,C);
//print(C,nC);
int r=merge(C,nC,m);
printf("%d\n",r);
}
return 0;
}
#include <string.h>
#include <memory.h>
//将数字从十进制转换到制定进制
//input:
//n: 要转换的数字(十进制)
//m: 要转换的进制
//output:
//a,l: 要求进制的数字,和位数,[0]为最低位
void split(int n, int m,int a[],int &l)
{
l=0;
for(;n;n/=m)
{
a[l++]=n%m;
}
}
void print(int a[],int l)
{
for(int i=0;i<l;i++)
printf("%d ",a[i]);
printf("\n");
}
//将指定进制的数字做xor运算
//input:
//a,n1,b,n2
//m
//output:
//c
int xor(int const a[],int n1, int const b[],int n2, int m, int c[])
{
int k=n1>n2?n1:n2;
for(int i=0;i<k;i++)
{
c[i]=(a[i]+b[i])%m;
}
return k;
}
int A[50];
int nA=0;
int nB=0;
int B[50];
int nC=0;
int C[50];
//将数字从指定进制转换到十进制
int merge(int const a[],int n1, int m)
{
int r=0;
for(int i=0;i<n1;i++)
{
r =r*m+a[n1-1-i];
}
return r;
}
int main(int argc, char *argv[])
{
int T;
scanf("%d",&T);
while(T--)
{
int a,b=0,m;
char s[1000+1];
scanf("%d %s %d",&a,s,&b);
m=strlen(s)+1;
//printf("a %d b %d m %d\n",a,b,m);
memset(A,0,sizeof(A));
memset(B,0,sizeof(B));
memset(C,0,sizeof(C));
split(a,m,A,nA);
split(b,m,B,nB);
//print(A,nA);
//print(B,nB);
nC=xor(A,nA,B,nB,m,C);
//print(C,nC);
int r=merge(C,nC,m);
printf("%d\n",r);
}
return 0;
}
B:有道搜索框
- 时间限制:
- 1000ms
- 内存限制:
- 131072kB
- 描述
- 在有道搜索框中,当输入一个或者多个字符时,搜索框会出现一定数量的提示,如下图所示:
现在给你N个单词和一些查询,请输出提示结果,为了简化这个问题,只需要输出以查询词为前缀的并且按字典序排列的最前面的8个单词,如果符合要求的单词一个也没有请只输出当前查询词。 - 输入
- 第一行是一个正整数N,表示词表中有N个单词。
接下来有N行,每行都有一个单词,注意词表中的单词可能有重复,请忽略掉重复单词。所有的单词都由小写字母组成。
接下来的一行有一个正整数Q,表示接下来有Q个查询。
接下来Q行,每行有一个单词,表示一个查询词,所有的查询词也都是由小写字母组成,并且所有的单词以及查询的长度都不超过20,且都不为空
其中:N<=10000,Q<=10000 - 输出
- 对于每个查询,输出一行,按顺序输出该查询词的提示结果,用空格隔开。
- 样例输入
10
a
ab
hello
that
those
dict
youdao
world
your
dictionary
6
bob
d
dict
dicti
yo
z- 样例输出
bob
dict dictionary
dict dictionary
dictionary
youdao your
z
代码
// test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <assert.h>
struct node
{
char end;
long child[26]; //idx of its child
node()
:end(0)
{
memset(child,0,sizeof(child));
}
}nodes[10000*20];
long n=0;
void insert(char const s[])
{
long idx=0;
for(int i=0,m=strlen(s);i<m;i++)
{
long *pidx=&nodes[idx].child[s[i]-'a'];
if(*pidx==0)
{
idx=*pidx=++n;
}
else
idx=*pidx;
if(i==m-1)
nodes[idx].end=1;
}
}
char str[20];
int nStr=0;
void print(long idx)
{
if(nodes[idx].end)
{
str[nStr]=0;
printf("%s ",str);
}
for(int i=0;i<26;i++)
{
long idx2=nodes[idx].child[i];
if(idx2)
{
str[nStr++]=i+'a';
print(idx2);
nStr--;
}
}
}
void srch(char const s[])
{
bool find=true;
long idx=0;
for(int i=0,m=strlen(s);i<m;i++)
{
idx=nodes[idx].child[s[i]-'a'];
if(!idx)
{
find = false;
break;
}
}
if(!find)
printf("%s\n",s);
else
{
strcpy(str,s);
nStr=strlen(s);
print(idx);
printf("\n");
}
}
int main(int argc, char *argv[])
{
int N;
scanf("%d",&N);
while(N--)
{
char s[20];
scanf("%s",s);
insert(s);
}
//srch("");
scanf("%d",&N);
while(N--)
{
char s[20];
scanf("%s",s);
srch(s);
}
return 0;
}
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <assert.h>
struct node
{
char end;
long child[26]; //idx of its child
node()
:end(0)
{
memset(child,0,sizeof(child));
}
}nodes[10000*20];
long n=0;
void insert(char const s[])
{
long idx=0;
for(int i=0,m=strlen(s);i<m;i++)
{
long *pidx=&nodes[idx].child[s[i]-'a'];
if(*pidx==0)
{
idx=*pidx=++n;
}
else
idx=*pidx;
if(i==m-1)
nodes[idx].end=1;
}
}
char str[20];
int nStr=0;
void print(long idx)
{
if(nodes[idx].end)
{
str[nStr]=0;
printf("%s ",str);
}
for(int i=0;i<26;i++)
{
long idx2=nodes[idx].child[i];
if(idx2)
{
str[nStr++]=i+'a';
print(idx2);
nStr--;
}
}
}
void srch(char const s[])
{
bool find=true;
long idx=0;
for(int i=0,m=strlen(s);i<m;i++)
{
idx=nodes[idx].child[s[i]-'a'];
if(!idx)
{
find = false;
break;
}
}
if(!find)
printf("%s\n",s);
else
{
strcpy(str,s);
nStr=strlen(s);
print(idx);
printf("\n");
}
}
int main(int argc, char *argv[])
{
int N;
scanf("%d",&N);
while(N--)
{
char s[20];
scanf("%s",s);
insert(s);
}
//srch("");
scanf("%d",&N);
while(N--)
{
char s[20];
scanf("%s",s);
srch(s);
}
return 0;
}
C:最大和子序列
- 时间限制:
- 1000ms
- 内存限制:
- 131072kB
- 描述
- 给一个整数数组A={a1,a2,…an}, 将这个数组首尾相接连成一个环状,它的一个子序列是指这个数组连续的一段,比如a2,a3…ak,或者an,a1…ai。请从这个环上选取两个不重叠的非空子序列,使这两个子序列中的所有数字之和最大。
在三个样例中分别选取的子序列是:
样例一: {a1} {a3}
样例二: {a1} {a3}
样例三: {a5,a1} {a3} - 输入
- 输入的第一行包含一个正整数T(1<=T<=40),表示有T组测试数据。
接下来每个测试数据包含两行,第一行是一个正整数n(2<=n<=50000), 第二行是用空格隔开的数组A的n个数,依次为a1,a2,…an (|ai|<=10000)。 - 输出
- 每组数据输出一行,包含一个数,即所求的这两个子序列的元素之和。
- 样例输入
3
3
1 -1 0
4
1 -1 1 -1
5
1 -1 1 -1 1- 样例输出
1
2
3- 提示