写在最前面,计算机题目,大多数考察的都是思维能力,首先要完整的将题目多读两遍,明确题目的目的,然后再结合样例输入输出检测自己的想法是否是正确的;
A题:
考察点:快速幂的运用;


分析:
初始速度为1,每次脚踩脚会让速度翻倍,即乘以二,踩了n次,那么最后的速度就是2^n米每秒,如果用传统的方法那么时间复杂度为O(n),由于时间限制是400ms,当n过大时,运行就会超时,所以正确做法是使用快速幂,就可以将时间复杂度降低,代码如下:
#include<bits/stdc++.h>
using namespace std;
#define p 299792458
int main()
{
int n;
scanf("%d",&n);
long long base=2;
long long result=1;
while(n>0){
if(n&1){
result=(result%p*base%p)%p;
}
n>>=1;
base=(base*base)%p;
}
printf("%lld\n",result);
}B题:
考察点:递归思维;
分析:
这种考察思维的题,看完题目后去看样例输入输出对思维启发会有很大帮助,我们可以看到:
1只?时:?一定会被?吃点,然后?变成?,没有别的?,他一定不会被吃掉,所以最开始那只羊一定会被吃掉;
2只?时:假如有一只狼把羊吃了,他自己变成了羊,那他就一定会被另一只狼吃掉,所以他不敢吃羊;所以两只狼都不敢吃羊;
3只狼时:假入有一只狼把羊吃掉了,那他自己就变成了羊,然后现在的状态就是两只狼一只羊,回到了上一种状态,另外两只狼不敢吃羊,吃掉羊的那只狼就不用担心自己是否会被吃,所以羊一定会被吃掉;
4只狼时:就假设一只狼吃掉了羊,回到第三只狼的状态……
由上述规律可得,有奇数只狼时,羊一定会被吃掉,偶数只狼时,不会被吃掉;
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
if(n%2==0){
printf("NO");
}else {
printf("YES");
}
}之所以这题没做出来,一个是因为自己着急了,二一个是觉得这种思维题估计会很难想到,于是猜测了只有当n=1时会被吃掉其他不会被吃的情况,提交后错了,于是就没有思考这题了,也算是很可惜吧,要是把思考最后一题的时间拿来思考这题,应该还是能过的。
C题
考察点:思维;

分析:
首先要将输入的数的回文数构建出来,然后再来判断是不是素数,我们可以分析出,最大的回文数为999999999,将近10亿!这么大的数,构建素数表再来做判断显然不可能,编译都要实际二十多秒(当时我还以为是软件的问题),所以大概率这题也就是用最常规的方法做判断是不是素数, 难点在于构建回文数,emmm,好吧其实也不算是难点,写多了就会了,
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int main()
{
string s;
getline(cin,s);
int i;
int l1=s.length();
long long ans=0;
for(i=0;i<=2*l1-1;i++){
if(l1==1){
ans=s[i]-'0';
break;
}
if(i<l1-1){
ans=ans*10+s[i]-'0';
}else if(i>=l1){
ans=ans*10+s[2*l1-i-1]-'0';
}
}
for(i=1;i<=8&&ans<=8;i++){
if(ans==2||ans==3||ans==7||ans==5){
printf("isprime\n");
break;
}else {
printf("noprime\n");
break;
}
}
for(i=3;i<=sqrt(double(ans));i++){
if(ans%i==0){
//printf("%d\n",i);
printf("noprime\n");
break;
}
if(i>sqrt(double(ans))-1){
printf("isprime\n");
break;
}
}
}E题:
考察知识点:快速幂,前缀和一点gcd的结合运用


分析:
在m轮循环中,每一个数都或多或少的乘以了2或3,我们的目的是求最大公约数,按常理来说,直接每一轮分别乘就是了,但是!注意这题的时间限制是500ms,也就是这题大概率是要在运行时间卡我们,那么常规的方法大概率就是不行的,根据本周所学知识,其实就是考察快速幂的使用,也就是每个位置上的数成了多少个2,乘了多少个3,然后用快速幂求出来,所以我们就要分别记录下来每个位置乘了多少2和3,可以用两个数组来实现;但如果我们就是每个位置去挨个加一,那就和直接乘2,乘三没有区别了,还是多了一个for循环,造成超时,所以我们要用前缀和的方法来记录,这样就能少一层循环;
记录好后,我们就要来找最小公约数,每个位置上的数都是1乘以了多少个2,乘以多少个3,也就是说多乘以了一个2的那个数一定是少乘一个2的那个数的倍数,那我们就只需要找乘2次数最少的,3也一样,所以我们找到乘2的最小次数,乘3的最小次数,然后再利用快速幂求出最大公约数即可;
//分别记录下每个位置的数乘了多少次2,3, 可以利用前缀和;
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
#define p 999999998
#define ll long long
ll quick(ll base,ll n)
{
ll result=1;
while(n>0){
if(n&1){
result=result*base%p;
}
n>>=1;
base=base*base%p;
}
return result;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
int a2[N],a3[N];//前缀和记录2和3的个数;
int x[N],y[N];
//都初始化为0;
memset(a2,0,sizeof(a2));
memset(a3,0,sizeof(a3));
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
while(m--){
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
if(x==2){
a2[l]++;
a2[r+1]--;
}
if(x==3){
a3[l]++;
a3[r+1]--;
}
}
//找到所有元素中乘的次数最少次的那个;
int min2=a2[1],min3=a3[1];
for(int i=1;i<=n;i++){
x[i]=x[i-1]+a2[i];
y[i]=y[i-1]+a3[i];
min2=min(min2,x[i]);
min3=min(min3,y[i]);
}
ll ans=(quick(2,min2)%p*quick(3,min3)%p)%p;
printf("%lld\n",ans);
}
}G题
考察点:排序、前缀和、思维能力,

分析:
在读完题目后,我们要明确目的“使所有人的平均等待时间最短”,平均等待时间其实就是所有人的等待时间之和除以总人数,所以我们要使找所有人的等待时间之和最小化;
那么当前面一个人在洗澡的时候,后面所有人也就在等待,对于第一个人,她直接就进去洗澡了,她的等待时间为0,她在洗澡的时候,后面的人也就在等待,第二个人进去的时候,后面的人也就在等待,也就是说,后面的人的等待时间也就是前面洗澡的人的洗澡时间之和,所以这里可以想到要用到前缀和,那如何让总的等待时间最短呢?也就是让洗澡时间最长的人最后洗,这样其他人的等待时间就大幅缩减了,也就是说,最好的排序方式是按照洗澡时间从短到长排序,那么最后一个人洗澡时就没人需要等待了,所以这里要用到排序的知识,那么平均等待时间也就是所有人等待时间之和除以总人数;
我的:
想法是:建立结构体数组,一个值表达洗澡时间,一个值表达最开始输入这个洗澡时间时它的位置,然后按照思路做。而我一直被卡着的原因是:没想通怎么记录下最开始的位置,其实不用结构体,用另一个数组也能做,但可能太紧张,太着急了,所以一直没想出来;
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int b[N];
struct piont {
int x;
int y;
}a[N];
int main()
{
int n,i,j;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&a[i].x);
a[i].y=i;
int t=i;
for(j=i-1;j>0;j--){
if(a[t].x<a[j].x){
int aa=a[t].x;
int bb=a[t].y;
a[t].x=a[j].x;
a[t].y=a[j].y;
a[j].x=aa;
a[j].y=bb;
t--;
}
}
}
for(i=1;i<=n;i++){
b[i]=b[i-1]+a[i].x;
if(i==n){
printf("%d \n",a[i].y);
break;
}
printf("%d ",a[i].y);
}
double sum=0.00;
for(i=1;i<n;i++){
sum+=(b[i]*1.00)/n;
}
printf("%.2f\n",sum);
}最优解(出题人的解):
其实也是使用了结构体;
#include<bits/stdc++.h>
using namespace std;
struct st{
int x;
int y;
};
st a[1005];
bool rule(st i,st j){
if(i.y <j.y){
return true;
}else if(i.y==j.y){
if(i.x<j.x){
return true;
}else{
return false;
}
}else{
return false;
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
a[i].x=i;
scanf("%d",&a[i].y);
}
sort(a,a+n,rule);
long long ans=0;
int m=n;
for(int i=0;i<n;i++){
ans+=a[i].y*(m-1);
m--;
printf("%d ",a[i].x+1);
}
printf("\n%.2lf",ans*1.0/n);
}