Codeforces Round #725 (Div. 3)补题

C. Number of Pairs

在这里插入图片描述
这道题大体的题意就是在一个序列中找满足ai+aj在一个范围内的数对。
首先这道题是可以给序列排序的,因为题目中虽然给出i<j的条件,但是原来成立的序对i , j 无论相对顺序如何在新的序列中改变,他们对答案的贡献一定是与原序列一致的。明确这一点之后使用 sort 就可以使得序列有序,有序就具有单调性,就可以使用二分降低时间复杂度。
二分其实要找的就是下标,如图所示:
在这里插入图片描述

最外层for循环枚举 ai 的下标,通过二分来找符合条件的 aj (红笔描述的两点性质是二分的依据),这样在这个符合条件的区间里的aj都满足性质,那么区间长度就是对答案的一次贡献。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
long long int a[N];
long long int ll, rr;
int bnri1(long long int l, long long int r, long long int k) {
    while(l<r)
    {
        int mid=l+r+1>>1;
        if(a[mid]<k) l=mid;
        else r=mid-1;
    }
    return l;
}
long long int bnri2(long long int l, long long int r, long long int k) {
    while(l<r)
    {
        int mid=l+r+1>>1;
        if(a[mid]<=k) l=mid;
        else r=mid-1;
    }
    return l;
}
int main() {
    int tt;
    cin >> tt;
    while (tt--) 
    {
        int n;
        cin >> n >> ll >> rr;
        for (int i = 1; i <= n; i++) 
            scanf("%lld", &a[i]);
        sort(a+1, a + n+1);
        long long int cnt = 0;
        for (int i = 1; i <= n; i++)
            cnt += bnri2(i, n, rr - a[i]) -bnri1(i , n, ll - a[i]);
        cout<<cnt<<endl;
    }
    return 0;
}

这道题同样可以使用 lower_bound( )和upper_bound( )来实现二分。
一个有序数组中:
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,可以找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,可以找到数字在数组中的下标。
因为地址的线性储存,两段地址做差可以得到区间长度。
在这里插入图片描述

F. Interesting Function

在这里插入图片描述
题意大概就是从a到b,逐步加1过渡,看b的尾缀改变的个数。看样例即可。
比赛的时候以为是数位DP,然而仔细找一下规律发现并不难。从1到11——改变了12次,其中1~11每个个位数累加对答案贡献了1,十位数过渡的那一次对答案贡献了1,加起来是12。
所以从1到 n 的答案是比较好求的,就是个位,十位,百位…对答案的贡献都是1,所以答案就是各个位数的贡献之和:

 while(x)
{
  ans+=x;
  x/=10;//统计十进制位的个数,每个位对答案都有1:1的贡献
}
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int get(int x)
{
    int ans=0;
    while(x)
    {
      ans+=x;
      x/=10;
    }
    return ans;
}
void solve()
{
    int l,r;
    cin>>l>>r;
    int ans=get(r)-get(l);
    cout<<ans<<endl;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        solve();
    }
}

D. Another Problem About Dividing Numbers

在这里插入图片描述

本题借鉴csdn大佬的题解
在这里插入图片描述
本来想的是求约数个数,最后发现约数个数不代表最大步数,还是得求出质因数的个数,逐一削减才可以得到相等的最大步数,最小步数比较好想。
这个最少步数的两次,可以理解为a除以a,b除以b,1=1。最小步数一次可以理解为大的一个数除了__gcd(a,b)。

#include <bits/stdc++.h>
using namespace std;
 
const int N = 1e5 + 100;//质数的Max
 
int st[N], primes[N], idx;
 
void get_primes()//线性筛筛质数
{   int cnt=0;
    for (int i = 2; i <= N; i ++ )
    {
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] <= N / i; j ++ )
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}
int get(int x)//对筛完的质数分解质因数
{   
    int t=0;
    for(int i=0;primes[i]<=sqrt(x);i++)//因为a,b最大值1e9,开方不超过1e5,所以筛质数筛到 N = 1e5 +10;
    {
        while(x%primes[i]==0)
        {
            x/=primes[i];
            t++;
        }
    }
    if(x>1) t++;
    return t;
}
 
int main()
{
	get_primes();
	int t;
	scanf("%d", &t);
	while(t --)
	{
	int a, b, k;
	long long int  l, r = 0;
	scanf("%d%d%d", &a, &b, &k);
	r += get(a);
	r += get(b);
	if(a == b) l = 0;
	else if(__gcd(a, b) == a || __gcd(a, b) == b) l = 1;
	else l = 2;
	if(l == 0) 
	{
		if(k <= r && k != 1)
		puts("YES");
		else puts("NO");
		continue;
	}
	if(k >= l && k <= r) 
	{
		puts("YES");
	   continue;
	}
	puts("NO");
	}
   
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值