天梯赛题目总结

本文介绍了C++中的编程技术,包括求解连续因子的算法、优化平方根运算、素数的快速判断、树的前序、中序和后续遍历、二叉搜索树的建立、邻接表的双向创建以及深度优先搜索和二维DFS的使用方法。
摘要由CSDN通过智能技术生成

(1)L1-006 连续因子

求连续因子的题可以使用两层循环

#include<stdio.h>
#include<math.h>
int main()
{
    int n = 0;
    scanf("%d", &n);
    int i = 0,j=0, a = 0, sum=0,num = 0,temp=0,qidian=0,longqidian=0;
    int x = sqrt(n);//这里解释一下,为什么sqrt(n),因为我们最少的因子就两个为素数,假设这个不是素数,极限求最大的两个值相乘等于该数就是开根号,所以这里是节省运行时间,防止超时
    for (i = 2;i <= x;i++)
    {
        num = 0;
        sum = n;
        qidian = i;
        for (j = i;sum%j==0&&sum!=0;j++)
        {
            sum /= j;
            num++;
        }
        if (num > temp)
        {
            temp = num;//筛选最长因子个数
            longqidian = qidian;
        }
    }
    if (temp == 0)
        printf("1\n%d", n);
    else
    {
        printf("%d\n", temp);
        i = longqidian;
        while (i < longqidian + temp)
        {
            if (i != longqidian)
                printf("*");
            printf("%d", i);
            i++;
        }
    }
    return 0;
}

(2)加负号左对齐,不加右对齐

int main() {
    int start, end;
    cin >> start >> end;
    int total = 0;
    for (int i = start; i <= end; i++) {
        if ((i - start + 1) % 5 == 0 || i == end) {
            printf("%-5d\n", i);
        }
        else printf("%-5d", i);
        total += i;
    }

    cout << "Sum = " << total;

    return 0;
}

(3)字符与数字转换

char->int :c-'0'

int->char :i+'0'
(4)输出字母

while(g||p||l||t){
        if(g){
            cout<<"G";
            g--;
        }
        if(p){
            cout<<"P";
            p--;
        }
        if(l) {
            cout<<"L";
            l--;
        }
        if(t){
            cout<<"T";
            t--;
        }
    }

(5)素数判定

bool isSushu(int n){
    if(n==2||n==3||n==5){return true;}
    else if((n%6==1||n%6==5)&&n>6){
        for(int i=2;i<=sqrt(n);i++){
            if(n%i==0) return false;
        }
        return true;
    }
    return false;
}

bool isprime(int x) {
    if (x == 1 || x == 4)return false;
    if (x == 2 || x == 3)return true;
    else if (x % 6 != 1 && x % 6 != 5)return false;
    for (int i = 5; i <= sqrt(x); i += 6) {
        if (x%i== 0 || x%(i+2) == 0)return 0;
    }
    return 1;
}
(6)遇到有很多属性的,可以考虑新建结构体更方便
(7)数字求模题目要谨慎,要一下子反应过来题目在考什么

#include<stdio.h>
int main()
{
    int n,m;
    int x[100];
    while(~scanf("%d %d",&n,&m))
    {
        int i,j,t=0;
        --m;
        while(m>0)
        {
            x[t++]=m%26;
            m=m/26;
        }
        for(i=0; i<n-t; ++i)
            printf("z");
        for(i=t-1; i>=0; --i)
            printf("%c",'z'-x[i]);
    }
}
(8)变量一定要初始化!!!!吃过很多亏了

(9)静静的推荐(蛮经典)

#include<bits/stdc++.h>
using  namespace std;
bool cmp(pair<int, int> a, pair<int, int>b) {
    if (a.first == b.first) {
        return a.second < b.second;
    }
    else return a.first > b.first;
}
int main() {
    int n, k, s;
    cin >> n >> k >> s;
    vector<int>vec(300,0);
    int num=0;
    while(n){
        n--;
        int pat1,pat2;
        cin>>pat1>>pat2;
        if(pat1>=175&&pat2>=s){
            num++;
        }
        else if(pat1>=175&&vec[pat1]<k){
            vec[pat1]++;
            num++;
        }
    }
    cout<<num;

    return 0;
}
(10)L2-006 树的遍历(很重要,掌握前序中序后续序列构建树的方法)

Node* buildTree(vector<int>post, vector<int>ins, int i, int j, int n) {
    if (n <= 0)return NULL;
    int d = post[i + n - 1];
    Node* node = new Node(d);
    int p = j;
    while (ins[p] != d)p++;
    int k = p - j;
    node->left = buildTree(post, ins, i, j, k);
    node->right = buildTree(post, ins, i + k, p + 1, n - k - 1);
    return node;
}
BNode* buildtree(vector<int>pre, vector<int>ins, int i, int j, int n) {
    if (n <= 0)return NULL;
    int d = pre[i];
    BNode* node = new BNode(d);
    int p = j;
    while (ins[p] != d) {
        p++;
    }
    int k = p - j;
    node->left = buildtree(pre, ins, i + 1, j, k);
    node->right = buildtree(pre, ins, i + k + 1, p + 1, n - k - 1);
    return node;
}
void reverseTree(BNode* root) {
    if (root == NULL)return;
    swap(root->left, root->right);
    reverseTree(root->left);
    reverseTree(root->right);
}


void bianli(BNode* root, vector<int>& res) {
    queue<BNode* >que;
    if (root == NULL)return;
    que.push(root);
    while (!que.empty()) {
        BNode* node = que.front();
        que.pop();
        res.push_back(node->data);
        if (node->left != NULL)
            que.push(node->left);
        if (node->right != NULL)
            que.push(node->right);
    }
}

(11)二叉搜索树(二叉排序树,二叉查找树)的建立和遍历

#include <stdio.h>
#include <stdlib.h>

typedef struct node {
    int data;
    struct node *left;
    struct node *right;
}Node;

typedef struct tree {
    Node *root;
}Tree;

void create_tree(Tree *tree, int val)
{
    Node *node = (Node*)malloc(sizeof(Node));  //定于一个节点,将数放到节点中
    node->data = val;
    node->left = NULL;
    node->right = NULL;
    
    if (tree->root == NULL) {
        tree->root = node;   //如果根为空,就将这个节点放到根节点
    }
    else {
        Node *temp = tree->root;  //定义指针指向根节点
        while (temp != NULL) {
            if (val < temp->data) {  //如果要放入的值小于根节点
                if (temp->left == NULL) {  //根节点左孩为空,就直接放入
                    temp->left = node;
                    return;
                }
                else {
                    temp = temp->left;  //根节点左孩不为空,就指向下一个左孩节点
                }
            }
            else {
                if (temp->right == NULL) { //右孩为空,直接放入
                    temp->right = node;
                    return;
                }
                else {
                    temp = temp->right;  //右孩不为空,指向下一个右孩节点
                }
            }
        }
    }
}
void preorder(Node *node)
{
    if (node != NULL) {
        printf("data is %d\n",node->data);
        preorder(node->left);
        preorder(node->right);
    }
}

void inorder(Node *node)
{
    if (node != NULL) {
        inorder(node->left);
        printf("data is %d\n",node->data);
        inorder(node->right);
    }
}

void postorder(Node *node)
{
    if (node != NULL) {
        postorder(node->left);
        postorder(node->right);
        printf("data is %d\n",node->data);
    }
}

int main(int argc, char **argv)
{
    int a[7] = {7,4,5,6,1,8,9};
    Tree tree;
    tree.root = NULL;
    int i;
    int len = sizeof(a) / sizeof(int);
    for (i=0; i<len; i++) {
        create_tree(&tree, a[i]);
    }

    inorder(tree.root);
    return 0;
}
void find(int left, int right) {
    if (left > right)return;
    int ll = left + 1;
    int rr = right;
    if (!flag) {
        while (ll <= right && num[ll] < num[left])ll++;
        while (rr > left && num[rr] >= num[left])rr--;
    }
    else {
        while (ll <= right && num[ll] >= num[left])ll++;
        while (rr > left && num[rr] < num[left])rr--;
    }
    if (ll - rr != 1)return;
    find(left + 1, rr);
    find(ll, right);
    result.push_back(num[left]);
}
(12)假如有两种关系,可以考虑分开存两种关系

L2-010 排座位
 

#include<bits/stdc++.h>
using namespace std;
const int n = 105;
int f[n];
int enamy[n][n] = { 0 };

int find(int x) {
    if (x == f[x])return x;
    f[x] = find(f[x]);
    return f[x];
}
int main() {
    for (int i =1; i <=n; i++) {
        f[i] = i;
    }
    int n, m, k;
    cin >> n >> m >> k;
    int x1, x2, relation;
    for (int i = 0; i <m; i++) {
        cin >> x1 >> x2 >> relation;
        if (relation == 1) {
            if (find(x1) != find(x2))f[find(x2)] = x1;
        }
        else {
            enamy[x1][x2] = 1;
            enamy[x2][x1] = 1;
        }
    }
    while (k--) {
        cin>>x1>>x2;
        if (find(x1) == find(x2) && enamy[x1][x2] == 0) cout << "No problem" << endl;
        else if (find(x1) != find(x2) && enamy[x1][x2] == 0)cout << "OK" << endl;
        else if (find(x1) == find(x2) && enamy[x1][x2] == 1)cout << "OK but..." << endl;
        else if(find(x1) != find(x2) && enamy[x1][x2] == 1)cout << "No way" << endl;
    }
    return 0;
}

(13)创建完全二叉树(堆):用数组就可以了

void createHeap(vector<int>& heap, int x) {
    int size = heap.size();
    heap.push_back(x);
    while (size > 0 && heap[(size - 1) / 2] > heap[size]) {
        swap(heap[(size - 1) / 2], heap[size]);
        size = (size - 1) / 2;
    }
}
(14)多项式除法

while (idx1 >= idx2) {
        double xishu = a[idx1] / b[idx2];
        shang[idx1 - idx2] = xishu;
        for (int i = idx1, j = idx2; j >= 0 && i >= 0; i--, j--) {
            a[i] = a[i] - xishu * b[j];
        }
        while (!a[idx1])idx1--;
    }
    shuchu(idx3, shang);

(15)深度优先搜索//在每个节点都至少有两个后继节点的情况下比较好用
void dfs(int id, double gong, double r) {
        vis[id]=1;
        if (dedao[id]) {
            gongli[id] = gong* fangda[id];
            return;
        }
        for (int i = 0; i < f[id].size(); i++) {
            if (!vis[f[id][i]]) {
                vis[f[id][i]] = 1;
                gongli[f[id][i]] = gong* (1 - r);
                dfs(f[id][i], gong * (1 - r), r);
            }
        }
}
void dfs(int id, int num) {
    if (num >= 4)return;
    vis[id] = 1;
    for (int i = 0; i < vec[id].size(); i++) {
        if (!vis[vec[id][i]]) {
            vis[vec[id][i]] = 1;
            dfs(vec[id][i], num + 1);
        }
        else {
            flag = 1;
            break;
        }
    }
}
 

(16)无向图的邻接表一定要记得创建双向的,树可以创建单向的

for (int i = 0; i < e; i++) {
        int start, end;
        cin >> start >> end;
        v[start].push_back(end);
        v[end].push_back(start);//创建邻接表的时候一定要注意双向建立
        //cout << start << end<<endl;
    }
 

(17)完全二叉树的层序遍历:直接用数组表示

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,ans=1;
int a[N],b[N],top=1;
void dfs(int x){
    if(x<=n){
        dfs(x*2);
        dfs(x*2+1);    
        b[x]=a[top++];
    }    
}
int main()
{
    int i,j;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    dfs(1);
    for(i=1;i<=n;i++){
        if(i!=1) printf(" ");
        printf("%d",b[i]);
    }
    return 0;
    
}
(18)二维dfs

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

int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

void dfs(int x, int y, int& flag, int m, int n, vector<vector<char>>&mp) {
    if (x < 0 || x >= n || y < 0 || y >= m)return;
    if (mp[x][y] == '0')return;
    if (mp[x][y] !='0') {
        if (mp[x][y] != '1')flag = 1;
        mp[x][y] = '0';
        for (int i = 0; i < 4; i++) {
            dfs(x + dx[i], y + dy[i], flag, m, n, mp);
        }
    }
}

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<char>>mp(n, vector<char>(m, '0'));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            char num;
            cin >> num;
            mp[i][j] = num;
        }
    }
    int res = 0;
    int baozang = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            int flag = 0;
            if (mp[i][j] > '0') {
                res++;
                dfs(i, j, flag, m, n, mp);
            }
            if (flag)baozang++;
        }
    }
    cout << res << " " << baozang;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值