刷题记录(NC15173 The Biggest Water Problem,NC22164 更相减损术,NC208813 求逆序数,NC207028 第k小数)

NC15173 The Biggest Water Problem

题目链接

关键点: 

1、递归:每一次求当前数的位上的数字相加后的数字,再继续用算出来的数字继续递归

2、当算出来的数字为个位数时,就可以退出输出

完整代码:

# include <cstdio>
# include <iostream>
using namespace std;
typedef long long ll;
ll n;
ll deal(ll x)
{
    if (x<10)
        return x;
    int sum = 0;
    while (x)
    {
        sum+=x%10;
        x/=10;
    }
    return deal(sum);
}
int main()
{
    scanf("%lld", &n);
    printf("%lld", deal(n));
    
    
    return 0;
}

 NC22164 更相减损术

题目链接

关键点:

1、直接利用辗转相除法即可

完整代码

# include <cstdio>
# include <iostream>
using namespace std;
int gcd(int a, int b)
{
    if (b==0)
        return a;
    else
        return gcd(b, a%b);
}
int main()
{
    int a, b;
    cin>>a>>b;
    cout<<gcd(a, b);
      
    return 0;
}

NC208813 求逆序数

题目链接

关键点:

1、递归分治来缩小问题规模,采用归并排序的思想,先求左边一半的逆序数,再求右边一半的逆序数,最后再求左区间内大于右区间的个数.

2、核心部分求求左区间内大于右区间的个数,分别比较左右两个区间的数,左区间的开头下标为l,尾为mid,右区间为r,一旦当前的左区间的数(下标为l)大于右区间的数(下标为r),又因为两个区间都是从大到小排序的,因此,左区间后面的数也会大于当前的右区间,所以个数加上(mid-r+1)

int p = l, q = mid+1;
    for (int i=l; i<=r; i++)
    {
        if ((q>r)||(p<=mid)&&a[p]<a[q])
            b[i] = a[p++];
        else
        {
            b[i] = a[q++];
            cnt += (mid-p+1);
        }
    }

完整代码:

# include <iostream>
# include <cstdio>
using namespace std;
int n;
int a[2010];
int b[2010];
int cnt;
void mergesort(int l, int mid, int r)
{
    int p = l, q = mid+1;
    for (int i=l; i<=r; i++)
    {
        if ((q>r)||(p<=mid)&&a[p]<a[q])
            b[i] = a[p++];
        else
        {
            b[i] = a[q++];
            cnt += (mid-p+1);
        }
    }
    for (int i=l; i<=r; i++)
        a[i]=b[i];
}
void merge(int l, int r)
{
    if (l==r)
        return ;
    int mid = (l+r)/2;
    merge(l, mid);
    merge(mid+1, r);
    mergesort(l, mid, r);
}
int main()
{
    cin>>n;
    for (int i=1; i<=n; i++)
        cin>>a[i];
    merge(1, n);
    cout<<cnt;
    
    
    return 0;
}

NC207028 第k小数

题目链接

关键点: 

1、采用快排的思想:求一个数是否为第k个数,如果当前数为第a(a>k)小数,那么从该数前面继续找第k小数,如果a<k,那么从该数找后面的第k小数,如果就是第k个数就返回

完整代码:

# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
int t;
int a[1000000*5+10];
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int find(int l, int r, int k)
{
    if (l==r) return a[l];
    int i = l, j = r;
    int mid = (l+r)/2;
    while (i<=j)
    {
        while (a[i]<a[mid]) i++;
        while (a[j]>a[mid]) j--;
        if (i<=j)
        {
            swap(a[i], a[j]);
            i++;
            j--;
        }
    }
    if (k<=j) return find(l, j, k);
    else if (i<=k) return find(i, r, k);
    else return a[k];
}
int main()
{
    t = read();
    while (t--)
    {
        int n, k;
        n = read();
        k = read();
        for (int i=1; i<=n; i++)
            a[i] = read();
//         printf("%d\n", find(1, n, k));
        sort(a+1, a+1+n);
        printf("%d\n", a[k]);
    }
    
    
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值