受到语法的限制(就连数组都不能涉及太多),绝大部分的常用算法都无法考察,此次比赛更多的是对逻辑思维能力的锻炼。
签到题,直接模2即可。
#include
int main(){
int n;
scanf("%d", &n);
if(n % 2){
printf("YES\n");
}else{
printf("NO\n");
}
return 0;
}
简单的数位分离。多次循环,通过模10再除10分离出各个位置上的数字并求和,最后判断该数字模上它的数位和是否是0即可。
#include
int main(){
int n;
scanf("%d", &n);
//t是n的备份
int t = n;
//s用来记录各数位之和
int s = 0;
//数位分离
while(t){
s = s + (t % 10);
t /= 10;
}
//判断n是否可以被s整除
if(n % s){
printf("no\n");
}else{
printf("yes\n");
}
return 0;
}
博弈论入门题,通过简单的证明可以得知,当初始的石子数量为奇数时,alpha必胜,当初始的石子数量为偶数时,小轩必胜。证明过程如下:如果初始的石子数量为奇数,则不管小轩如何去分,都会产生一个奇数个数的石堆和一个偶数个数的石堆,此时Alpha可以扔掉奇数个数的石堆,将偶数个数的石堆分成两个奇数个数的石堆,这样不管小轩扔掉哪一个石堆,小轩的必然还剩下一个奇数的石堆,小轩继续(且必须)将奇数的石堆分成一个奇数的石堆和一个偶数的石堆,Alpha继续上一次的步骤。这样持续下去,到小轩分割石堆的时候,石堆必然有奇数个石子,因为石子是越分越少,最后小轩手上必然出现石堆中只有一个石子的情况,此时小轩无法分割,即alpha必胜。当初始的石子数量为偶数时,也可以使用相同的方法证明,这里不再赘述。
#include
int main(){
int n;
scanf("%d", &n);
//n组读入
while(n--){
int m;
scanf("%d", &m);
//模2为0 则ap wins
if(m % 2){
printf("ap wins\n");
}else{
//模2不为0 则xx wins
printf("xx wins\n");
}
}
return 0;
}
模拟+特判
#include
int main(){
int t;
scanf("%d", &t);
while(t--){
int n, m;
scanf("%d%d", &n, &m);
//如果初始可乐数0 则一瓶都喝不到
if(n == 0){
printf("0\n");
}else if(m <= 1){
//如果0个或者1个空瓶就可以兑换一瓶新的可乐 则可以一直喝下去
printf("Excited!\n");
}else{
//sum用来统计一共喝了多少瓶可乐 bottle用来记录当前空瓶子的数量
int sum = n, bottle = n;
//如果瓶子可以换就一直换下去
while(bottle >= m){
int t = bottle / m;
sum = sum + t;
bottle = bottle % m;
bottle += t;
}
printf("%d\n", sum);
}
}
return 0;
}
入门级线性DP(数字三角形模型),因为每次只能向上或者向左,所以我们定义一个状态为 dp[i][j] 表示能够到达 (i, j) 这个点的所有方案的能量最大值。所以动态转移方程为:dp[i][j] = arr[i][j] + max(dp[i+1][j], dp[i][j+1])。
#include
int arr[1010][1010];
int dp[1010][1010];
int main(){
int n;
scanf("%d", &n);
//读入整个地图
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
scanf("%d", &arr[i][j]);
}
}
//动态规划
for(int i = n; i >= 1; i--){
for(int j = n; j >= 1; j--){
if(dp[i + 1][j] > dp[i][j + 1]){
//从下面过来
dp[i][j] = dp[i + 1][j] + arr[i][j];
}else{
//从右边过来
dp[i][j] = dp[i][j + 1] + arr[i][j];
}
}
}
//输出结果
printf("%d\n", dp[1][1]);
return 0;
}
签到题,因为只需要对三个数进行排序,所以只需手动模拟交换排序的核心过程即可。
#include
int main(){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
//如果a大于b 则a和b交换位置
if(a > b){
int t = a;
a = b;
b = t;
}
//如果a大于c 则a和c交换位置
if(a > c){
int t = a;
a = c;
c = t;
}
//如果b大于c 则b和c交换位置
if(b > c){
int t = b;
b = c;
c = t;
}
//输出结果
printf("%d %d %d\n", a, b, c);
return 0;
}
此题为防AK题,难度较大,看不懂的同学可以直接跳过,不做要求。考察的是多重背包问题的二进制优化(后台数据较大,多重背包的朴素解法会被卡掉)。
#include
long long w[2010], cnt;
bool f[100010];
long long a[2010], s[2010];
int t, n, k;
int main(){
scanf("%d", &t);
//t组数据
while(t--){
//多重背包问题的二进制优化
cnt = 1;
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%lld", &a[i]);
}
for(int i = 1; i <= n; ++i){
scanf("%lld", &s[i]);
}
scanf("%d", &k);
//二进制优化 分解成01背包问题
for(int i = 1; i <= n; ++i){
int t = 1;
while(t <= s[i]){
w[cnt] = a[i] * t;
cnt++;
s[i] -= t;
t = t * 2;
}
if(s[i] > 0){
w[cnt] = s[i] * a[i];
cnt++;
}
}
n = cnt - 1;
for(int i = 0; i <= 100010; ++i){
f[i] = false;
}
//动态规划
f[0] = true;
for(int i = 1; i <= n; ++i){
for(int j = k; j >= w[i]; --j){
if(!f[j]){
f[j] = f[j-w[i]] ? true : false;
}
}
if(f[k]){
break;
}
}
//输出结果
if(f[k]){
printf("Yes\n");
}else{
printf("No\n");
}
}
return 0;
}
循环计算出阶乘,然后数位分离再统计即可。阶乘的结果可能会炸int,必须用long long来存,考虑到大部分同学并没有学习到数组,这里展示不用数组的写法,用数组的话,代码会精简很多。
#include
//用于存储0~9 各个数字出现的次数
int n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
int main(){
int n;
scanf("%d", &n);
//20的阶乘会爆int 但是在long long的范围内 所以使用long long来存储
long long ans = 1;
//计算阶乘
for(int i = 1; i <= n; ++i){
ans = ans * i;
}
//数位分离
while(ans){
//对应的数字次数+1
if(ans % 10 == 0){
n0++;
}else if(ans % 10 == 1){
n1++;
}else if(ans % 10 == 2){
n2++;
}else if(ans % 10 == 3){
n3++;
}else if(ans % 10 == 4){
n4++;
}else if(ans % 10 == 5){
n5++;
}else if(ans % 10 == 6){
n6++;
}else if(ans % 10 == 7){
n7++;
}else if(ans % 10 == 8){
n8++;
}else if(ans % 10 == 9){
n9++;
}
ans /= 10;
}
//输出结果
printf("%d %d %d %d %d %d %d %d %d %d\n", n0, n1, n2, n3, n4, n5, n6, n7, n8, n9);
return 0;
}
循环读入,维护最大值即可。
#include
using namespace std;
int n, t;
int main(){
scanf("%d", &n);
//ans初始化为-1 ans用来存储最高的票数 idx用来存储最高票数的编号
int ans = -1, idx = 0;
for(int i = 1; i <= n; ++i){
scanf("%d", &t);
//如果当前选手的票数比之前的所有人都高 则更新最大值
if(t > ans){
ans = t;
idx = i;
}
}
//输出结果
printf("%d\n", idx);
printf("%d\n", ans);
return 0;
}