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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章