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