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