L1-3
由原先需要unsigned long long
或者py
才能过,改为只需要LL
能过L2-1
中担心有考生忘记闰年如何判断,增加了闰年以及每个月的月数L2-4
增强了数据,直接转十进制,再转回来过不了L3-2
卡掉了暴搜能拿接近满分L3-3
的难度得到平衡为了让题型更加符合天梯风格,我砍掉了6
道其他出题人想出的题,最终才展现出这份卷子
出题人:贝
《刀使女巫》
的主角的头发颜色是什么
正确答案为E
以下三种解题方法
4
月23
号比赛《刀使女巫》
的主角是棕色头发#include
int main(){
printf("E");
}
出题人:贝
#include
using namespace std;
#define el '\n'
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
int main()
{
cin.tie(0);
cout.tie(0);
rep(i, 1, 5)
cout << "beibei shi Jimei University zui cai de ren" << el;
}
出题人:赖
带入公式求结果
测试点详情 :1-2点送分,3点long long 4点unsigned long long
这个系列故事写的挺好的,大家赛后记得补一补故事(bushi
解题思路
直接带入公式
代码实现
#include
using namespace std;
unsigned long long a, b, c, x;
int main() {
cin >> a >> b >> c >> x;
unsigned long long ans = a * x * x + b * x + c;
cout << ans;
}
出题人:杰
兑换后的瓶子,也可以重复兑换,循环结构模拟兑换过程即可,直至不能再兑换
#include
using namespace std;
int n, k, m;
int main()
{
cin >> n >> k;
int ans = 0;
do {
ans += n;
m += n; //得到n个瓶盖
n = m / k;
m %= k;
}while(n);
cout << ans;
}
出题人:弛
#include
using namespace std;
#define ll long long
int main(){
int t;
scanf("%d",&t);
while(t--){
char a[110],b[110];
scanf("%s%s",a,b);
int ans=0;
char tt[110];
int alen=strlen(a),blen=strlen(b);
for(int i=0;i<alen;i++){
for(int j=0;j<blen;j++){
if(a[i]!=b[j])continue;
char temp[110];
temp[0]=a[i];
int k=1;
while(j+k<blen&&i+k<alen&&a[i+k]==b[j+k]){
temp[k]=a[i+k];
k++;
}
temp[k] = '\0';
if(k>ans){
ans=k;
strcpy(tt,temp);
}
else if(k==ans){
if(strcmp(tt,temp)>0)strcpy(tt,temp);
}
}
}
if(ans==0)
printf("NO\n");
else{
printf("YES\n");
printf("%d\n",ans);
printf("%s\n",tt);
}
}
}
出题人:贝
在二维数组出现不同的数字的数量是否超过 9 9 9个
map来统计
使用map
map.size() > 9
是否成立
#include
using namespace std;
int T, a, b;
int main()
{
cin >> T;
while (T--)
{
map<string, int> mp;
cin >> a >> b;
string k;
for (int i = 1; i <= a; ++ i)
{
for (int j = 1; j <= b; ++ j)
{
cin >> k;
++ mp[k];
}
}
if(mp.size() > 9)
cout << "YES";
else
cout << "NO" ;
if(T)
cout << '\n';
}
}
出题人:贝
出题报告
原本我还想卡掉double的精度,直接比较总和long long,精度肯定比直接比较平均值来的高,后面思索了一下,还是没刻意去卡
这题我设置了4个测试点
不会真有人用“lbn”、“LBN”来表示 a 0 a_0 a0对应的字符串?
测试点1,基本正确,4分
测试点2,最大数据,全部正确,得开long long ,10分
测试点3,基本正确,但是会被“lbn”,“LBN”卡掉,5分
测试点4,测试nobody,1分
因为 1 0 5 × 1 0 5 = 1 0 10 10^5 \times 10^5 =10^{10} 105×105=1010,所以需要开LL
#include
using namespace std;
typedef long long LL;
const int N = 110;
int T, n, m;
map<string , LL> last, now;
string name[N];
string b = "1", s;//因为S是由字母组成的,故用数字字符串来代表贝贝可以避免哈希冲突
//考察哈希中的状态设计
LL x;
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; i ++ )
{
cin >> x;
last[b] += x;
}
for (int i = 1; i <= n; i ++ )
{
cin >> s;
name[i] = s;
for (int i = 1; i <= m; i ++ )
{
cin >> x;
last[s] += x;
}
}
cin >> now[b];
int cnt = 0;
for (int i = 1; i <= n; i ++ )
cin >> now[name[i]];
for (auto it : last)
{
if(it.second >= last[b] && now[it.first] < now[b])
{//历史平均值比贝贝高,且报出成绩比贝贝低
cnt ++ ;
cout << it.first << endl;
}
}
if (cnt == 0)
cout << "Yeah! Nobody!" <<endl;
}
出题人:弛
#include
using namespace std;
#define ll long long
const int N=1e6+10;
int fa[N];
int find(int x){
if(fa[x]==x)return x;
else return fa[x]=find(fa[x]);
}
int main(){
int T;
cin>>T;
while(T--){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
fa[i]=i;
}
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
fa[find(v)]=find(u);
}
int num=0;
for(int i=1;i<=n;i++){
if(fa[i]==i)num++;
}
cout<<n-num<<endl;
}
}
出题人:勋
已知1900年1月1日是星期一,给定一个合法日期询问是星期几
很简单的一道日期模拟,只需要计算两个日期内差了多少天,%7即可。
#include
using namespace std;
string s[8]={"1","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};
int main() {
int y,m,d;
scanf("%d-%d-%d",&y,&m,&d);
int sum=0;
for(int i=1900; i<y; i++) {
if((i%4==0&&i%100!=0)||(i%400==0))
sum=sum+366;
else
sum=sum+365;
}
int r[12]={31,29,31,30,31,30,31,31,30,31,30,31};
int br[12]={31,28,31,30,31,30,31,31,30,31,30,31};
for(int i=0;i<m-1;i++){
if((y%4==0&&y%100!=0)||(y%400==0)){
sum+=r[i];
}else{
sum+=br[i];
}
}
sum+=d;
//printf("sum=%d\n",sum);
int t;
t=sum%7;
if(t==0){
cout<<s[7];
}else{
cout<<s[t];
}
return 0;
}
出题人:杰
维护高度:父亲的高度是所有儿子中最高高度 + 1 +1 +1 。 h i g h [ u ] = m a x ( h i g h [ v ] ) + 1 high[u]=max(high[v])+1 high[u]=max(high[v])+1
最后判等即可。
#include
using namespace std;
const int N=2e5+10;
vector<int>G[N];
int dep[N],high[N],n;
void dfs(int u,int fa){
dep[u]=dep[fa]+1;
high[u]=1;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v==fa)continue;
dfs(v,u);
high[u]=max(high[u],high[v]+1);
}
}
int main(){
int u,v;
cin>>n;
for(int i=1;i<n;i++){
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,0);
int ans=0;
for(int i=1;i<=n;i++){
if(dep[i]==high[i]){
ans++;
}
}
cout<<ans<<'\n';
for(int i=1;i<=n;i++){
if(dep[i]==high[i]){
cout<<i<<" ";
}
}
}
出题人:赖
给你一个json字符串要你转化成java代码
测试点详情 :1-3点送分,4点出现嵌套List 5-6点嵌套list+最后一个是Object类型和object嵌套
一行输入所以用getline输入因为不能保证其中有没有空格,所以遇到空格可以直接略过。
观察json显然可以根据":“和”,"轻松分开key和value(只要不在{}和[]内因此要判断现在循环是否在{}和[]内)
分开KV之后分别保存在两个数组内,接下来只要写一个函数分析Value是什么类型的就可以了,显然每一种类型都有自己与其他不一样的样式:
object型:value内第一个字符是'{'
list型:value内第一个字符是'['
string型:value内第一个字符是'"'
bool型:value内第一个字符是字母
Float型:value内包含'.'
如果上面都不是那么一定是Integer型了
是不是很简单呢?
接下来只要简单用代码随便搞搞就可以了。
#include
using namespace std;
string str, ls = "";
vector<string> lef, rig;
int outTag, outTag2, iss, inList;
string checkType(string key, string str) {
if (str[0] == '{') {
if (iss) {
return "Object";
}
if ('a' <= key[0] && key[0] <= 'z') {
key[0] = key[0] + 'A' - 'a';
}
return key;
}
if (str[0] == '[') {
iss = true;
return "List<" + checkType(key, str.substr(1, str.length() - 2)) + ">";
}
if (str[0] == '\"') return "String";
if (str == "true" || str == "false") return "Boolean";
for (int i = 0; i < str.length(); i++)
if (str[i] == '.') return "Float";
return "Integer";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
getline(cin, str);
for (int i = 1; i < str.length() - 1; i++) {
if (str[i] == ' ') continue;
if (str[i] == '{') outTag2 ++;
if (str[i] == '}') outTag2 --;
if (str[i] == '[') outTag ++;
if (str[i] == ']') outTag --;
if (str[i] == ':' && !outTag && !outTag2) {
ls.erase(remove(ls.begin(), ls.end(), '\"'), ls.end());
lef.push_back(ls);
ls = "";
continue;
}
if (str[i] == ',' && !outTag && !outTag2) {
rig.push_back(ls);
ls = "";
continue;
}
ls += str[i];
}
rig.push_back(ls);
for (int i = 0; i < rig.size(); i++) {
iss = false;
inList = false;
string ans = checkType(lef[i], rig[i]);
cout << "public " << ans << " " << lef[i] << (iss ? "s" : "") << ";\n";
}
}
出题人:贝idea,弛出题
对于该题,一个关键点是,22
位的62
进制是会超过C++
语言中所有整数类型的最大表示范围的,若采用
x
进制转换为y
进制,不借助10
进制的做法可以过#include
using namespace std;
const int MAXN = 1500;
int x, y;
char s[MAXN], ans[MAXN];
int t[MAXN], res[MAXN];
int getnum(char c)//将字符转化为数字
{
if(c >= '0' && c <= '9') return c - '0';
if(c >= 'A' && c <= 'Z') return c - 'A' + 10;
else return c - 'a' + 36;
}
char getch(int num)//将数字转化为字符
{
if(num <= 9) return num + '0';
if(num <= 35) return num + 'A' - 10;
else return num + 'a' - 36;
}
void work()
{
int len = (int)strlen(s+1);
for(int i = 1; i <= len; i++) t[i] = getnum(s[i]);
for(int j = 1, k = 0; j <= len; )//j为当前最高位,模拟短除法
{
for(int i = j; i < len; i++)//等价于高精除法
{
t[i+1] += t[i] % y * x;
t[i] /= y;
}
res[++k] = t[len] % y;//得到此次除y的余数
t[len] /= y;
while(j <= len && !t[j]) j++;
for(int i = 1; i <= k; i++) ans[i] = getch(res[k-i+1]);
//倒序输出
}
}
int main()
{
scanf("%d%d%s", &x, &y, s+1);
work();
printf("%s\n", ans+1);
return 0;
}
出题人:举
一个字符串,找出长度为k的子序列,要字典序最小。
既然要使子序列的字典序最小,那么越小的字符应该尽可能的在序列开头。所以应该把最小的字符放在序列中。
分别存在a-z每个字符的下标。假设当前为原字符串s
中下标为now=0
,子序列长度为kk
,从字符a开始找,找到这么一个位置 pos
,使得pos>=now && s.size()-pos>=k-kk
。 s.size()-pos>=k-kk
这个式子是要判断从pos
往后是否还有足够的字符可以构成长度为k的序列。
#include
using namespace std;
const int maxm = 2e6 + 5;
vector<int> g[26];
int cur[26];
string s;
int n, k;
void slove() {
for (int i = 0; i < 26; i++) {
g[i].clear();
cur[i] = 0;
}
cin >> s >> k;
n = s.size();
for (int i = 0; i < n; i++) {
g[s[i] - 'a'].push_back(i);
}
string ans;
int now = 0;
int flag = 0;
for (int kk = 0; kk < k; kk++) {
for (int i = 0; i < 26; i++) {
// 使用二分查找进行优化
int idx = (lower_bound(g[i].begin(), g[i].end(), now) - g[i].begin());
if (idx < g[i].size() && (s.size() - g[i][idx]) < (k - kk))continue;
if (idx < g[i].size()) {
ans += ('a' + i);
now = g[i][idx]+1;
break;
}
}
}
cout << ans << endl;
}
int main() {
ios::sync_with_stdio(false);
slove();
return 0;
}
出题人:勋
有n个地点,m条路径,同时每条航线有概率出现LJL,输出从起点s到终点t的最短路径,该路径要保证遇到LJL概率最小。
1. 完全图
2. 链
3. $n=1000,m=10000$随机数据
4. $n=10000,m=100000$随机数据
5. $n=100000,m=200000$随机数据
6. 无边
7. 多个相同地点数,需要概率最大
很明显解法是最短路径,所谓路过地点数就是将每个路径看成长度为1的最短路。
这里涉及一个最短路径的变形题:多权值最短路径。也就是dijk算更新最短路的时候如果需要相等的情况需要根据第二关键字判断:
要求的路径首先是最短路,其次才是遇到LJL概率最小的路径。求路径上遇到LJL的概率可以用反面事件,1-LJL分身消失的概率,后者是每段路概率乘积。可以维护从起点到各点最短路径上都没遇到LJL的概率,这样就成了一个多权值最短路问题,与普通最短路差别就在于dis[now]+w == dis[to]时,如果此时从当前点到达下一个点会使得第二个权值更优那就更改路线,否则不必改动。
#include
#include
#include
#include
#include
#include
#include
#define pii pair<int, int>
using namespace std;
//首先需要路径最短,其次需要遇到LJL概率最低
int n, m, s, t, dis[100005], head[100005], cnt, pre[100005], st[100005];
bool vis[100005];
double p[100005];
struct edge
{
int to, w, next;
}e[500005];
void add(int u, int v, int w)
{
e[++cnt].to = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt;
}
void dijkstra()
{
dis[s] = 1;
p[s] = 1.0;
priority_queue<pii, vector<pii>, greater<pii> > a;
a.push(make_pair(dis[s], s));
while(a.size())
{
int now = a.top().second;
a.pop();
if(vis[now])
continue;
vis[now] = true;
for(int i = head[now]; i; i = e[i].next)
{
int to = e[i].to, w = e[i].w;
if(dis[now]+1 < dis[to])
{
dis[to] = dis[now]+1;
pre[to] = now;
p[to] = p[now]*(100.0-w)/100.0;
a.push(make_pair(dis[to], to));
}
else if(dis[now]+1 == dis[to])
{
if(p[now]*(100.0-w)/100.0 > p[to])
{
p[to] = p[now]*(100.0-w)/100.0;
pre[to] = now;
}
}
}
}
}
signed main()
{
cin >> n >> m >> s >> t;
for(int i = 1; i <= m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w), add(v, u, w);
//cout<
}
memset(dis, 0x3f, sizeof dis);
dijkstra();
if(dis[t]!=1061109567)printf("%d %.10f\n", dis[t], p[t]);
else cout<<"-1";
return 0;
}
出题人:杰
#include
using namespace std;
const int N=2e5+10;
vector<int>a[N];
vector<pair<int,int>>q[N];
int ans[N],c[N],n,m,k;
void update(int x,int k) {
for(int i=x; i<=n; i+=i&(-i))c[i]+=k;
}
int query(int l,int r) {
int sum=0;
for(int i=r; i>0; i-=i&(-i))sum+=c[i];
for(int i=l-1; i>0; i-=i&(-i))sum-=c[i];
return sum;
}
int main() {
int l,r;
cin>>n>>m>>k;
for(int i=1; i<=m; i++) {
cin>>l>>r;
a[l].push_back(r);
}
for(int i=1; i<=k; i++) {
cin>>l>>r;
q[l].push_back(make_pair(i,r));
}
for(int l=n; l>=1; l--) {
for(int i=0; i<a[l].size(); i++) {
int r=a[l][i];
update(r,1);
}
for(int i=0; i<q[l].size(); i++) {
int id=q[l][i].first,r=q[l][i].second;
ans[id]=query(l,r);
}
}
for(int i=1; i<=k; i++)cout<<ans[i]<<" ";
return 0;
}