Contest3032 - 计科2101~2104算法设计与分析上机作业03

目录

问题 A: 质数

问题 B: 分治法求解全排列问题 

 问题 C: 数的计数

问题 D: 最大公共子序列问题

 问题 E: 分解式的个数

问题 F: 矩阵最优连乘问题


问题 A: 质数

题目描述

判断给定的一组正整数是否为质数。

输入

第一行为测试数据的个数n,下面n行每行为一个待测试的正整数x,2≤x≤10000。n<=100000

输出

对每一个待测试的正整数x,如果x是质数,输出一行yes,否则输出一行no。

样例输入 

2
5
10

样例输出 

yes
no

素数筛

#include <bits/stdc++.h>
using namespace std;
#define int long long

bool prim[100005];

void fun(){
    for(int i=2;i<=1005;i++){
        if(prim[i]==false){
            for(int j=2*i;j<=100005;j+=i){
                prim[j]=true;
            }
        }
    }
}

signed main(){
    fun();
    int n;
    cin>>n;
    while(n--){
        int num;
        cin>>num;
        if(prim[num]==false){
            cout<<"yes"<<endl;
        }
        else{
            cout<<"no"<<endl;
        }
    }
}

问题 B: 分治法求解全排列问题 

题目描述

设R=(1, 2, .., n),计算R的全排列。 分治法求解全排列的算法思想: 设R=(1, 2, .., n)的全排列为P(R), 若R=(),则P()=(); 否则,P(R)={(1)P(2, 3, .., n),(2)P(1, 3, .., n), (3)P(2, 1, .., n), .., (n)P(2, .., n-1, 1)}; 同样地,P(2, 3, .., n)={(2){3, 4, .., n}, (3){2, 4, .., n}, .., (n){3, .., n-1, 2}}

输入

输入为一组不大于7的整数。

输出

对每个输入的整数n,用分治法计算并输出1..n的全排列。

样例输入 

1
2
3

样例输出 

1 
1 2 
2 1 
1 2 3 
1 3 2 
2 1 3 
2 3 1 
3 2 1 
3 1 2 

换位置,再分治,再换回来。。。 

#include<bits/stdc++.h>
using namespace std;
 
int fun(int *a,int l,int r){
    if(l==r){
        for(int i=0;i<=r;i++)
            cout<<a[i]<<" ";
        cout<<endl;
    }
    else{
        for(int i=l;i<=r;i++){
            swap(a[l],a[i]);
            fun(a,l+1,r);
            swap(a[l],a[i]);
        }       
    }
    return 0;
}
 
 
int main(){
    int n;
    while(cin>>n){
        int *a = (int *)malloc(sizeof(int) * n);
        for(int i=1;i<=n;i++){
            a[i-1]=i;
        }
        fun(a,0,n-1);
    }   
}

 问题 C: 数的计数

题目描述

我们要求找出具有下列性质数的个数(包含输入的自然数n)。

先输入一个自然数 n (n≤1000),然后对此自然数按照如下方法进行处理:
1· 不作任何处理;
2. 在它的左边加上一个自然数,但该自然数不能超过原数的一半;
3. 加上数后,继续按此规则进行处理,直到不能再加自然数为止。

输入

自然数n

输出

满足条件的数的个数

样例输入 

6

样例输出 

6

提示

样例的六个满足条件的数是6、16、26、126、36、136

 从n/2开始遍历辣,然后有点递归的意思,你懂我意思吧?

#include<bits/stdc++.h>
#define int long long
using namespace std;
 
int a[1005];
 
int fun(int n){
    int ans=0;
    if(n==1){
        return 1;
    }
    for(int i=n/2;i>=1;i--){
        if(a[i]!=0){
            ans+=a[i];
        }
        else{
            a[i]=fun(i);
            ans+=a[i];
        }
    }
    return ans+1;
}
 
signed main(){
    int n;
    cin>>n;
    cout<<fun(n)<<endl;
    return 0;
}

问题 D: 最大公共子序列问题

题目描述

对序列X=(x1, x2, .., xm),定义其子序列为(xi1, xi2, .., xik),i1<i2<..<ik。 请计算两个序列X=(x1, x2, .., xm),Y=(y1, y2, .., yn)的最长公共子序列的长度。

输入

输入为若干行,每行是一个计算题目,每行包括两个长度不超过100的字符串,中间用空格隔开。

输出

对每一行中的两个字符串,计算并输出其最大公共子序列的长度。 每一行输入的计算结果输出一行。

样例输入 

a a
a ab
abcd dcba
abcd bc
abcdef aabacfe

样例输出 

1
1
1
2
4

动态规划,你懂我意思吧?

#include<bits/stdc++.h>
#define int long long
using namespace std;
 
int c[105][105];
 
signed main(){
    string s1,s2;
    while(cin>>s1>>s2){
        int len1=s1.length();
        int len2=s2.length();
        for(int i=1;i<=len1;i++){
            for(int j=1;j<=len2;j++){
                if(s1[i-1]==s2[j-1]){
                    c[i][j]=c[i-1][j-1]+1;
                }
                else{
                    c[i][j]=max(c[i-1][j],c[i][j-1]);
                }
            }
        } 
        cout<<c[len1][len2]<<endl;
    }
    return 0;
}

 问题 E: 分解式的个数

题目描述

大于1的正整数可以分解成一组因子的乘积,例如12可以分解成:12、6*2、4*3、3*4、3*2*2、2*6、2*3*2、2*2*3,共8个分解式。请设计算法,计算指定的大于1的正整数的分解式的个数。

输入

第一行为测试用例个数n,n≤100000。 从第二行开始,共有n行,每行为一个大于1的正整数m,m≤10001。

输出

对每个测试用例m,输出其分解式的个数,每个输出占一行。

样例输入 

2
4
12

样例输出 

2
8

 递归啊,还是递归,你懂我意思嘛?

#include <bits/stdc++.h>
using namespace std;
#define int long long

int ans=0;

void fun(int n){
    ans++;
    for(int i=n-1;i>1;i--){
        if(n%i==0){
            fun(i);
        }
    }
    return;
}

signed main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        ans=0;
        fun(n);
        cout<<ans<<endl;
    }
    return 0;
}

问题 F: 矩阵最优连乘问题

题目描述

已知一组连乘矩阵的各维长度,要求计算并输出计算量最小的计算顺序表达式。

输入

每行为一组连乘矩阵的各维长度,行中第一个数字是连乘矩阵的个数n,n≤100,后面是n+1个维长。 矩阵个数为0表示输入结束。

输出

对每行输入,计算最优计算顺序,并以括号形式将计算表达式输出,各矩阵用A0, A1, ..的形式表示。

样例输入 

1 10 20
2 10 20 30
3 10 20 30 40
6 30 35 15 5 10 20 25
0

样例输出 

A0
A0A1
(A0A1)A2
(A0(A1A2))((A3A4)A5)

提示

输出格式中,不要有多余的括号。

区间dp,你懂我意思吧?

不懂算了,其实我也不懂

#include <iostream>
#include <cstring>
using namespace std;

const int MAXN = 105;

int n, A[MAXN];
int dp[MAXN][MAXN], s[MAXN][MAXN];
int flag1=0;
int flag2=0;

void print(int i, int j) {
    if (i == j) cout << "A" << i-1;
    else {
        if(i==1&&flag1==0){
            flag1++;
        }
        else
       
        cout << "(";
    
    
        print(i, s[i][j]);
        print(s[i][j]+1, j);
       
        if(j==n&&flag2==0){
            flag2++;
        }
        else
        cout << ")";
    
    }
}

int main() {
    while (cin >> n && n) {
        flag1=0;
        flag2=0;
        for (int i = 0; i <= n; i++) cin >> A[i];
        memset(dp, 0, sizeof(dp));
        for (int len = 2; len <= n; len++) {
            for (int i = 1; i <= n-len+1; i++) {
                int j = i+len-1;
                dp[i][j] = 0x3f3f3f3f;
                for (int k = i; k < j; k++) {
                    int tmp = dp[i][k] + dp[k+1][j] + A[i-1]*A[k]*A[j];
                    if (tmp < dp[i][j]) {
                        dp[i][j] = tmp;
                        s[i][j] = k;
                    }
                }
            }
        }
        print(1, n);
        cout << endl;
    }
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嗯嗯你说的对

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值