传智杯

感受:

​ 个人参加的b组,3道签到题+1道暴力/算法题+1道算法题。

​ 前三题卡到我的是看错题了,舍去小数部分看成整数输出,所以拿了double整数输出(四舍五入),导致wa了。

​ 第四题找二进制规律优化,因为不会就只写了一个暴力的解法过了3/4左右(?可能吧,一个代码TLE1-16都有过)数据。

题解:

A.组原成绩

A

等级:语法题

解析:

​ 依据题意直接输出整数即可。

代码:

1
2
3
4
5
6
7
8
9
10
11
#include<bits/stdc++.h>
using namespace std;
int main()
{
double t,h,e;
cin>>t>>h>>e;
double s=0.2*t+h*0.3+e*0.5;
int s1=s;
printf("%d",s1);
return 0;
}

B.报告赋分

B

等级:语法题

解析:

​ 给定一个t,接下来t行每行有一个卷面基础分a和页数p。

根据页数p减卷面分(题意)就行了。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;cin>>t;
while(t--)
{
int a,b;
cin>>a>>b;
if(b<16)a=max(a-10,0);
else if(b>20)a=max(a-(b-20),0);
cout<<a<<endl;
}
return 0;
}

C.竞争得分

C

等级:语法题

解析:

​ n表示人数,接下来n个数a1-an。

用数组存a1-an,用ma,mi存最大值和最小值。然后每个数进行一遍得分的运算+输出就行了。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
double a[N];
int main()
{
int n;cin>>n;
double ma=0,mi=10000;
for(int i=1;i<=n;i++)
{
cin>>a[i];
ma=max(ma,a[i]);
mi=min(mi,a[i]);
}
for(int i=1;i<=n;i++)
{
a[i]=100*(a[i]-mi)/(ma-mi);
int sb=a[i];//直接整数输出double的话会因为小数部分四舍五入而出错
printf("%d ",sb);
}
return 0;
}

D.小卡与质数2

D

等级:算法题

解析:二进制规律优化

​ 我的解法是一种简单的暴力写法。首先筛质数板子把1e6的所有质数筛出来,然后让小于x的非负整数与其按位异或,最后利用二分查找异或后的数是否是质数,是sum++。时间复杂度O(nmlogcnt),铁过不了但是交的代码会在#1-#16之间TLE,且每次基本不相同。

​ 正解后补。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//我知道我过不了但是TLE数据一直在变的代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6+10;
int primes[N],cnt;
bool st[N];
void init(int n)
{
for(int i=2;i<=n;i++)
{
if(!st[i])primes[cnt++]=i;
for(int j=0;primes[j]*i<=n;j++)
{
st[primes[j]*i]=1;
if(i%primes[j]==0)break;
}
}
}
int main()
{
int n;
cin>>n;
init(1000010);
while(n--)
{
int x;cin>>x;
int sum=0;
for(int i=0;i<x;i++)
{
int t1=x^i;

int t=lower_bound(primes,primes+cnt,t1)-primes;
if(primes[t]==t1)sum++;
}
cout<<sum<<endl;
}

}
//周围巨佬的AC代码
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=2e6+10;
int pr[N],idx,len=0,res=0;
bool st[N];
void init(int n)
{
for(int i=2;i<=n;i++)
{
if(!st[i]) pr[idx++]=i;
for(int j=0;pr[j]<=n/i;j++)
{
st[pr[j]*i]=1;
if(i%pr[j]==0) break;
}
}
}
int find(int x)
{
int num=1,len=0;
while(x)
{
num=num*2;
if(x&1)
{
int t=1;
for(int i=1;i<=len;i++) t=t*2;
//cout<<num<<' '<<t<<' ';
int r=upper_bound(pr,pr+idx,num-1)-pr;
int l=lower_bound(pr,pr+idx,t)-pr;
//cout<<l<<' '<<r<<endl;
res+=r-l;
}
len++;
x>>=1;
}
return num;
}
int main()
{
//freopen("1.txt","r",stdin);
init(N-10);
int T;
cin>>T;
//cout<<idx<<' ';
while(T--)
{
int x;
cin>>x;
len=0;res=0;
int l=1,r;
r=find(x);
cout<<res<<endl;
}
}

E.萝卜数据库

E

等级:语法题-算法题

解析:

​ 插入时:用二维数组第一维存字段x,第二维存值y,数组值存出现次数。

​ 查找时:ma[x] [ymi-yma]之和。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//二维数组
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N][N],sum[N];
int main()
{
int n,k;
cin>>n>>k;
int b,p,x,y;
for(int i=1;i<=n;i++)
{
cin>>b;
if(b==1)
{
cin>>p;
for(int i=1;i<=p;i++)
{
cin>>x>>y;
a[x][y]++;
}
}
else
{
int yma,ymi;
cin>>x>>ymi>>yma;

int sum=0;
for(int i=ymi;i<=yma;i++)
{

sum+=a[x][i];
//cout<<endl<<x<<i<<endl;
}
cout<<sum<<endl;
}
}
}
//哈希写法
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N][N],sum[N];
unordered_map<int,int> ma[N];

int main()
{
int n,k;
cin>>n>>k;
int b,p,x,y;
for(int i=1;i<=n;i++)
{
cin>>b;
if(b==1)
{
cin>>p;
for(int i=1;i<=p;i++)
{
cin>>x>>y;
ma[x][y]++;
//cout<<' '<<x<<' '<<y<<ma[x][y]<<endl;
}
}
else
{
int yma,ymi;
cin>>x>>ymi>>yma;

int sum=0;
for(int i=ymi;i<=yma;i++)
{

sum+=ma[x][i];
//cout<<endl<<x<<i<<endl;
}
cout<<sum<<endl;
}
}
}