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;
}