2024年春季学期《算法分析与设计》练习6

A:X星数列

题目描述

爱冒险的X星人在一艘海底沉船上发现了一串神秘数列,这个数列的前8项如下:
5, 8, 18, 34, 70, 138, 278, 554
X星人对这串数列产生了浓厚的兴趣,他希望你能够帮他发现这个神秘数列中所蕴含的规律,并且编写一个程序输出该数列前N项的和。
当输入一个正整数N时,请输出这个神秘数列前N项的和。

输入

单组输入,每组输入一个正整数N(N<=20)。

输出

输出一个正整数,对应这个数列前N项的和。

样例输入 Copy
4
样例输出 Copy
65
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3 + 5;
const int P = 131;
const int MOD=1e9+7;
int a[25];
void solve(){
    a[0]=5;
    a[1]=8;
    int n;
    cin>>n;
    for(int i=2;i<20;i++){
        a[i]=2*a[i-2]+a[i-1];
    }
    int s=0;
    for(int i=0;i<n;i++){
        s+=a[i];
    }
    cout<<s<<"\n";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
    //cin >> t;
    while (t--){
        solve();
    }
    return 0;
}

 B:X星计数

题目描述

热爱数学的X星人又发现了一个有趣的游戏,游戏名叫做:1的个数。
具体游戏规则为:给定一个十进制正整数,计算对应的二进制整数中有多少个1。

输入

多组输入。

第一行输入一个整数T(1<=T<=100),表示总共有T组数据。

接下来T行,每行一个十进制正整数n,其中1<=n<=1e^9。

输出

对于每一组输入,输出十进制正整数对应的二进制整数中包含的1的个数。

样例输入 Copy
3
1
9
12
样例输出 Copy
1
2
2
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3 + 5;
const int P = 131;
const int MOD=1e9+7;
int a[N];
void solve(){
    int n;
    cin>>n;
    int s=0;
    while(n){
        if(n%2==1){
            s++;
        }
        n/=2;
    }
    cout<<s<<"\n";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t;
    cin >> t;
    while (t--){
        solve();
    }
    return 0;
}

 C:第k大元素

题目描述

输入一个整数数组,请求出该数组的第k大元素。要求时间复杂度为O(n)。
 

输入

每组输入包括两行,第一行为k值;第二行为一个整数数组,两个数字之间用空格隔开。数组中元素个数小于1000。

输出

输出第k大元素的值,每个结果占一行

样例输入 Copy
2 
3 2 1 5 6 4
样例输出 Copy
5
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
void solve(){
    int n;
    cin>>n;
    multiset<int> st;
    int x;
    while(cin>>x){
        st.insert(x);
    }
    auto it=st.begin();
    advance(it,st.size()-n);
    cout<<*it<<"\n";
}
int main() {
    cin.tie(0)->sync_with_stdio(false);
    solve();
    return 0;
}

 D:棋盘覆盖问题

题目描述

在一个n×n (n = 2k)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。
在棋盘覆盖问题中,要用4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

 

输入

多组测试用例,每组测试用例包括两部分,
第一部分为方格的宽度n,
第二部分则为方格,特殊方格为-1,其他方格为0。
 

输出

输出覆盖后的方案

样例输入 Copy
4
-1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
样例输出 Copy
-1 2 4 4
2 2 1 4
3 1 1 5
3 3 5 5
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
int a[N][N];
int s=1;
void fun(int tr,int tc,int dr,int dc,int n){
    if(n==1){
        return;
    }
    n/=2;
    int ss=s++;
    if(dr<tr+n&&dc<tc+n){
        fun(tr,tc,dr,dc,n);
    }
    else{
        a[tr+n-1][tc+n-1]=ss;
        fun(tr,tc,tr+n-1,tc+n-1,n);
  
    }
        if(dr>=tr+n&&dc<tc+n){
        fun(tr+n,tc,dr,dc,n);
    }
    else{
        a[tr+n][tc+n-1]=ss;
        fun(tr+n,tc,tr+n-1,tc+n-1,n);
  
    }
    if(dr<tr+n&&dc>=tc+n){
        fun(tr,tc+n,dr,dc,n);
    }
    else{
        a[tr+n-1][tc+n]=ss;
        fun(tr,tc+n,tr+n-1,tc+n,n);
    }
    if(dr>=tr+n&&dc>=tc+n){
        fun(tr+n,tc+n,dr,dc,n);
    }
    else{
        a[tr+n][tc+n]=ss;
        fun(tr+n,tc+n,tr+n-1,tc+n,n);
    }
}
void solve(){
    int n;
    while(cin>>n){
        int x,y;
        s=1;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cin>>a[i][j];
                if(a[i][j]==-1){
                    x=i;
                    y=j;
                }
            }
        }
        fun(0,0,x,y,n);
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cout<<a[i][j]<<" \n"[j==n-1];
            }
        }
    }
}
int main() {
    cin.tie(0)->sync_with_stdio(false);
    solve();
    return 0;
}

 E:大整数乘法

题目描述

使用分治算法实现两个大整数相乘。

输入

两个十进制大整数,满足每一个整数长度为2^n且两个大整数的长度相等。(多组数据)

输出

两个大整数的乘积。

样例输入 Copy
1234 5678
样例输出 Copy
7006652
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6 + 5;
const int P = 131;
char a1[100001], b1[100001];
int a[100001], b[100001], i, x, len, j, c[100001];
void solve(){
     while(cin >> a1 >> b1){
        memset(c,0,sizeof c);
         int lena = strlen(a1);
    int lenb = strlen(b1);
    for (i = 1; i <= lena; i++)
        a[i] = a1[lena - i] - '0';
    for (i = 1; i <= lenb; i++)
        b[i] = b1[lenb - i] - '0'; 
    for (i = 1; i <= lenb; i++)
        for (j = 1; j <= lena; j++)
            c[i + j - 1] += a[j] * b[i];
    for (i = 1; i < lena + lenb; i++)
        if (c[i] > 9)
        {
            c[i + 1] += c[i] / 10;
            c[i] %= 10;
        }
    len = lena + lenb;
    while (c[len] == 0 && len > 1)
        len--;
    for (i = len; i >= 1; i--)
        cout << c[i];
    cout<<"\n";
    }
  
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    solve();
    return 0;
}

 F:整数划分问题之备忘录法

题目描述

使用备忘录法编写一个程序,求一个正整数n的所有划分个数。 
例如,输入3,输出3;输入4,输出5。 

输入

多组输入,每一组是一个正整数n。

输出

输出划分数。

样例输入 Copy
3
4
样例输出 Copy
3
5
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
int a[N][N];
int fun(int n,int m){
    if(n<1||m<1){
        return 0;
    }
    if(n==1||m==1){
        return 1;
    }
    if(n<m){
        return fun(n,n);
    }
    if(n==m){
        if(a[n][n-1]==0){
            a[n][n-1]=fun(n,n-1);
        }
        return 1+a[n][n-1];
    }
    if(n>m){
        if(a[n][m-1]==0){
            a[n][m-1]=fun(n,m-1);
        }
        if(a[n-m][m]==0){
            a[n-m][m]=fun(n-m,m);
        }
        return a[n][m-1]+a[n-m][m];
    }
}
void solve(){
    int n;
    while(cin>>n){
        cout<<fun(n,n)<<"\n";
    }
}
int main() {
    cin.tie(0)->sync_with_stdio(false);
    solve();
    return 0;
}

 G:大还是小?

题目描述

输入两个实数,判断第一个数大,第二个数大还是一样大。每个数的格式为:

[整数部分].[小数部分] 

简单起见,整数部分和小数部分都保证非空,且整数部分不会有前导 0。不过,小数部分的最 后可以有 0,因此 0.0和 0.000是一样大的。 

输入

输入包含不超过 20组数据。每组数据包含一行,有两个实数(格式如前所述)。每个实数都 包含不超过 100个字符。 

输出

对于每组数据,如果第一个数大,输出"Bigger"。如果第一个数小,输出"Smaller"。如果两个 数相同,输出"Same"。 

样例输入 Copy
1.0 2.0
0.00001 0.00000
0.0 0.000
样例输出 Copy
Case 1: Smaller
Case 2: Bigger
Case 3: Same
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e2 + 5;
const int P = 131;
void solve(){
    string a,b;
    int s=0;
    while(cin>>a>>b){
        s++;
        double x,y;
        x=stod(a);
        y=stod(b);
        if(x==y){
            cout<<"Case "<<s<<": Same\n";
        }
        else if(x>y){
            cout<<"Case "<<s<<": Bigger\n";
        }
        else{
            cout<<"Case "<<s<<": Smaller\n";
        }
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    solve();
    return 0;
}

 H:百舸争流

题目描述

橘子洲风景区位于湖南省长沙市市区对面的湘江江心,是湘江中最大的名洲,由南至北,横贯江心,西望
岳麓山,东临长沙城,四面环水,绵延数十里,狭处横约 40 米,宽处横约 140 米,形状是一个长岛,是
国家重点风景名胜区。
一天,N 名选手参加了一年一度的橘洲竞渡大赛,现在只剩下最后一场决赛了!
赛制为积分制,N 名选手的积分分别为 A1 到 AN。决赛的积分规则如下:第一名得 B1 分,第二名得 B2
分,……,第 m 名得 Bm 分,第 m+1 名至第 n 名不得分。最后第 i 名选手的总得分为 Ai 加上他在决
赛中的得分。
我们按总分为第一关键字、名字的字典序为第二关键字对选手进行排序。现告诉你一名选手的名字,希望
你告诉他,他最终的排名最前可能是多少,最后可能是多少。

输入

单组数据。
第一行为一个数 n,表示有 n 名选手 (1 ≤ n ≤ 105)。

接下来有 n 行,每行由一个字符串 S 和一个非负整数 Ai 表示,代表该人的名字和决赛之前的总分。

(名字仅由英文字母和数字表示,长度不超过 20,没有相同名字的两个人,0 ≤ Ai ≤ 106)。

接下来一个数 m(0 ≤ m ≤ n)。
接下来一行 m 个数字依次表示 B1, B2, B3, · · · , Bm (0 ≤ Bi ≤ 106)。
最后一个字符串表示询问的选手的名字。

输出

输出两个数,第一个表示最终排名最前可能多少,第二个表示最后可能多少。

样例输入 Copy
3
CH1 10
CH2 20
CH3 40
2
20 10
CH1
样例输出 Copy
2 3
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e6 +5;
const int M =1e9 +7;
int b[N];
struct S{
    string s;
    int num;
}a[N];
bool cmp(S i,S j){
    if(i.num==j.num){
        return i.s<j.s;
    }
    return i.num>j.num;
}
void solve(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i].s>>a[i].num;
    }
    int m;
    cin>>m;
    for(int i=1;i<=m;i++){
        cin>>b[i];
    }
    sort(b+1,b+m+1,greater<int>());
    string ss;
    cin>>ss;
    int sum=0;
    int f=0;
    for(int i=1;i<=n;i++){
        if(a[i].s==ss){
            a[i].num+=b[1];
            break;
        }
    }
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++){
        if(a[i].s==ss){
            f=i;
            sum=a[i].num;
            break;
        }
    }
    for(int i=n,j=f+1;i>=j+1&&j<=n;i--,j++){
        if((sum<a[i].num+b[j])||(a[i].num+b[j]==sum&&ss>a[i].s)){
            f++;
            i++;
        }
    }
    cout<<f<<" ";
    for(int i=1;i<=n;i++){
        if(a[i].s==ss){
            a[i].num-=b[1];
            a[i].num+=b[n];
            break;
        }
    }
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++){
        if(a[i].s==ss){
            f=i;
            sum=a[i].num;
            break;
        }
    }
    for(int i=f+1,j=n-f;j>=1&&i<=n;i++,j--){
        if((sum<a[i].num+b[j])||(a[i].num+b[j]==sum&&ss>a[i].s)){
            f++;
        }
        else{
            i--;
        }
    }
    cout<<f<<"\n";
}
int main() {
    cin.tie(0)->sync_with_stdio(false);
    solve();
    return 0;
}

 

  • 10
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值