北航2017级软件学院算法第一次上机题解

A 水水的斐波那契数列
签到题,基本的斐波那契数列

B SkyLee的超位魔法-黑暗丰穰之祭献
斐波那契的简单变形
AC代码:

#include <iostream>

using namespace std;

int goat(int n);

int main()
{
    int n;
    while(cin>>n)
        cout<<goat(n)<<endl;
}

int goat(int n){
    if(n<=4) return 1;
    else
        return goat(n-1)+goat(n-4);
}

C 芸如的入学测试
#include <iostream>
#include <cstdio>
#define mode 10007

using namespace std;

int N,Q,l,r,input;
long long an[1000001];


int main()
{
    while(cin>>N>>Q){
        scanf("%lld",an+1);
        for(int i=2;i<=N;i++){
            scanf("%d",&input);
            an[i]=an[i-1]+input;
        }
        while(Q--){
            scanf("%d %d",&l,&r);
            printf("%lld\n",(an[r]-an[l-1])%mode);
        }

    }
}

前缀和模板题

D 芸茹的课堂测试

#include <iostream>
#include <cstring>
#define mode 1000000007

using namespace std;

int n,i,len;
long long y;
char input[1000001];

int main()
{
    cin>>n;
    while(n--){
        scanf("%s",input);
        y=input[0]-'0';
        for(i=0;input[i]!='\0';i++);
        len=i;
        for(i=1;i<len;i++){
            y=(input[i]-'0'+(8*y))%mode;
        }
        cout<<y<<endl;
    }
}

霍纳法则。我觉得能用long long就用吧,不容易被卡。

E.比特手链:
可点击此处直接去我的另一篇博文查看

F.具体就是设一个数组f,f[i]表示i年来的艾露猫的数量,不过不包括死亡的。其余解释请看注释

#include <cstdio>
#define maxnum 55

int T,n;
int f[maxnum];

int main()
{
    f[1]=2,f[2]=2;
    for(int i=3;i<maxnum;i++){
        f[i]=f[i-1]+f[i-2];//正常斐波那契数列增长
        if(i>12)
            f[i]=f[i]-f[i-12];//如果大于12年,说明有些艾露猫失去了生育能力,得减掉这些失去生育能力的猫生下来的孩子数量,也就是f[i-12].那么这里有一个问题,i>20时,为什么不掉f[i-20]呢?这是因为如果要减的话,比如说f[30]=f[30]-f[30-12]-f[30-20],然后跑到31年年末时,有f[31]=f[31]-f[31-12]-f[31-20],此时f[11]>=f[10],也就是f[11]有一部分是f[10],我们减掉f[11]的话相当于把f[10]也给减掉了,但是其实31年年末去世的猫的数量并不是f[11],而是f[11]-f[10],所以这时候的f[31]的值就已经是有误的了,其余类似。所以就只能在减掉一次。
    }
    for(scanf("%d",&T);T--;){
        scanf("%d",&n);
        if(n<=20)
            printf("%d\n",f[n]);
        else
            printf("%d\n",f[n]-f[n-20]);
    }
}


这是代码里面第二段注释的内容

G.SkyLee在GameStop
这道题的题干有个点比较容易让人产生疑惑:“在同样快的试玩方案中,SkyLee会第一时间试玩他拿到的新游戏,然后尽量把字典序更小的游戏放在编号大的展示架上”。看题解前就觉得还有这种要求,肯定爆难,不做了。然后讲评课上助教说这个要求只在n<=2的时候才有效,后来我自个儿试了一下,发现还真是这么一回事。所以,以后还是别立马放弃,找几个例子试一下,特别是这种递归题。
这道题有两个子函数hanoi和hanoi_put,前者是用于玩游戏,后者是用于挪动玩过的游戏。
n= =1时,把第一个游戏挪到3号柱子上就可以了;n= =2时,较大的游戏挪到2,,较小的游戏挪到3即可;n>2时,把最上面的n-2个游戏挪到2上,然后1–>3,1–>1即可。

#include <cstdio>

using namespace std;

int n;

void hanoi_put(int n,int from,int via,int to){
    if(n==1){
        printf("get game from board %d\n"
               "put game to board %d\n",from,to);
    }
    else{
        hanoi_put(n-1,from,to,via);
        printf("get game from board %d\n"
               "put game to board %d\n",from,to);
        hanoi_put(n-1,via,from,to);
    }
}

void hanoi(int n,int from,int via,int to){
    if(n==1){
        printf("get game from board %d\n"
               "playing\n"
               "put game to board %d\n",from,to);
    }
    else{
        hanoi(n-1,from,to,via);
        printf("get game from board %d\n"
               "playing\n"
               "put game to board %d\n",from,to);
        hanoi_put(n-1,via,from,to);
    }
}

int main()
{
    while(~scanf("%d",&n)){
        if(n==1)
        {
            printf("get game from board 1\n"
                   "playing\n"
                   "put game to board 3\n"
                   "leave\n");
            continue;
        }
        if(n==2){
            printf("get game from board 1\n"
                   "playing\n"
                   "put game to board 2\n"
                   "get game from board 1\n"
                   "playing\n"
                   "put game to board 3\n"
                   "leave\n");
            continue;
        }
        if(n>2){
              hanoi(n-2,1,3,2);
              printf("get game from board 1\n"
                     "playing\n"
                     "put game to board 3\n"
                     "get game from board 1\n"
                     "playing\n"
                     "put game to board 1\n"
                     "leave\n");
        }
    }
}

H.序列优美差值:
这题跟1444题差不多,下面说几点个人觉得需要注意的地方:
1.就是需要写好完整的归并排序算法。
2.下标为lb的元素是不符合的,所以要用求更大元素的upperbound函数,但下标为rb的元素是符合的,所以要用求可以求相等元素的upperbound函数。它们的差值恰好为元素a[j]对应的配对数量。
3.关于递归,我觉得就是从高层开始往底层溯源,然后一直到无法递归的时候就开始计算,然后底层递归的计算结果最后又会服务于高层的递归。

#include <iostream>
#include <cstdio>
#include<algorithm>
#define maxnum 1000005
typedef long long ll;

using namespace std;

int T,n,L,R;
ll ans;
ll a[maxnum],b[maxnum];

void merge(int l,int r){
    int i,j,k;
    int mid=(l+r)>>1;
    int lb=l,rb=l;
    for(j=mid+1;j<=r;j++){
        lb=upper_bound(a+l,a+mid+1,a[j]-L)-a;

        rb=lower_bound(a+l,a+mid+1,a[j]-R)-a;

        ans+=lb-rb;
    }
    i=l,j=mid+1;
    for( k=l;i<=mid&&j<=r;k++){
        b[k]=a[i]<=a[j]?a[i++]:a[j++];
    }
    while(i<=mid) b[k++]=a[i++];
    while(j<=r) b[k++]=a[j++];
    for(k=l;k<=r;k++)
        a[k]=b[k];
}

void solve(int l,int r){
    int mid=(l+r)>>1;
    if(l<r){
        solve(l,mid);
        solve(mid+1,r);
        merge(l,r);
    }
}

int main()
{
    for(scanf("%d",&T);T--;){
        ans=0;
        scanf("%d%d%d",&n,&L,&R);
        for(int i=0;i<n;i++){
            scanf("%lld",&a[i]);
        }
        solve(0,n-1);
     //   for(int i=0;i<=n-1;i++)
     //       printf("%lld ",a[i]);
        printf("%lld\n",ans);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值