AtCoder Beginner Contest 172 C-D

AtCoder Beginner Contest 172 传送门

C - Tsundoku
题意:输入长度为n的a数组和长度为m的b数组,和一个k,从a和b数组的顶端(也就是最前)选出数构成子串,使得子串各数的和小于等于k,求构造的子串长度最大值。
题解:前缀和+二分
因为无法判断第一个是先放a[0]还是先放b[0],所以需要进行两次二分。
前缀和预处理a[i]表示a[0]+a[1]+…+a[i]
例如:假设第一个时先放a,当i=x,利用upper_bound(b,b+m,k-a[x])-b在b中找到第一个大于k-a[i]的下标pos,此时满足和小于等于k的子串长度为pos+i+1,每次都max记录子串长度最大解。
同理可以求得假设第一个先放b的情况,只需要最后max比较以不同数组先放入的最大解,就可求出最优解即可。

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define endl  '\n'
using namespace std;
const int MAX=1e6+7;
unsigned ll a[MAX],b[MAX],x[MAX],y[MAX];
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    int n,m,k,cnt;
    cin>>n>>m>>k;
	for(int i=0;i<n;i++)
	cin>>a[i];
	for(int i=1;i<n;i++)
	a[i]+=a[i-1];
	for(int i=0;i<m;i++)
	cin>>b[i];
	for(int i=1;i<m;i++)
	b[i]+=b[i-1];
	unsigned ll ans1=0,ans2=0,sum=0;
	for(ll i=0;i<n;i++)
	{
		sum=a[i];
		unsigned ll temp=k-sum;
		if(temp>k)break;
		unsigned ll pos=upper_bound(b,b+m,temp)-b;
		ans1=max(pos+i+1,ans1);
	}
	sum=0;
	for(ll i=0;i<m;i++)
	{
		sum=b[i];
		unsigned ll temp=k-sum;
		if(temp>k)break;
		unsigned ll pos=upper_bound(a,a+n,temp)-a;
		ans2=max(pos+i+1,ans2);
	}
	cout<<max(ans1,ans2);
    return 0;
}

D - Sum of Divisors
题解:f(x)表示x的因素个数(在[1,x]中,x有多少个因数),输入一个n,求在这里插入图片描述
题解:线性打表nlogn,直接暴力累加模拟。
还有个思路但是我没有实现:一个数的因数=一个数本身-这个数的欧拉函数+1,其中欧拉函数求得是某个数的质因数。

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define endl  '\n'
using namespace std;
const int MAX=1e7+7;
 ll a[MAX];
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    ll n,ans=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    	for(int j=i;j<=n;j+=i)
    		a[j]++;
    for(int i=1;i<=n;i++)
    {
    	ans+=i*a[i];
	}
	cout<<ans;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hrd535523596/article/details/106990243