PS: 有空再补,题目还没看呢QAQ
Solution
A
可以发现答案有单调性,即如果高度为 的房子可以盖出,则高度小于 的房子显然可以盖出。
于是我们果断二分。对于目前的高度 ,我们算出 材料总共缺少的数量,然后再与 一比即可得到二分的值是否可行。
时间复杂度 。
B
可以发现,满足要求的序列是两个差为 交互出现的序列,并且长度是偶数。
于是,我们直接枚举交替出现的这两个数中的一个,另一个也可以求出;然后直接求出对于这两个数形成的序列的最大和即可。注意特判 的情况。
另外,无合法序列输出的是 而不是 ,导致本蒟蒻 了好多次 QAQ。
C
比较擅长的数学题,奇迹般地
分钟切掉了
首先,推一推式子。假设这两个数分别是 ,其中 为这两个数的最大公约数;显然 ( 与 互质)且 均为自然数。
带入,得
至此,可以得到 或 。
但是,我们如何找到形成的序列的最大和呢?
考虑 。首先将这个序列按降序排序并去重,用 记录下每个数在原序列中出现的次数。
状态设计: 表示看到第 个数的最大和。
状态转移:
如果第 个数是奇数,那么 到 的所有数显然不能让它跟在后面,此时 ;
否则,我们考虑让它跟在第 的后面,即 ,其中 为满足 的唯一 。
我们可以用 记录下 这个数出现的位置,即可高效进行第二种转移。
时间复杂度 ,但是由于 的巨大常数导致在洛谷上跑得比蜗牛还慢(当然过了)。
Code
A
#include <bits/stdc++.h>
#define int long long
using namespace std;
int a,b,c,now,ans;
bool check(int x)
{
int need=(x*(x+1))/2,sumv;
sumv=max(need-a,0ll);
sumv+=max(need-b,0ll);
if (sumv<=c) return true;
else return false;
}
int Binary_search(int l,int r)
{
if (l+1==r||l==r)
{
if (check(r)) ans=max(ans,r);
if (check(l)) ans=max(ans,l);
return ans;
}
int mid=(l+r)>>1;
if (check(mid)) return Binary_search(mid,r);
else return Binary_search(l,mid);
}
signed main()
{
cin>>a>>b>>c;
cout<<Binary_search(0,1e9)<<endl;
return 0;
}
B
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,k,u,v,maxv,cnt,pos;
int a[2000005];
signed main()
{
cin>>n>>k;
for (int i=1;i<=n;i++)
{
cin>>u>>v;
a[u]+=v;
if (u*a[u]>maxv) maxv=u*a[u],pos=u;
}
if (k==0)
{
if (a[pos]>=2) return cout<<maxv<<endl,0;
else return cout<<"NO"<<endl,0;
}
else
{
maxv=0;
for (int i=0;i<=1000000;i++)
{
u=a[i],v=a[i+k];
cnt=min(u,v);
if (cnt>=2) maxv=max(maxv,cnt*i+cnt*(i+k));
}
if (maxv==0) cout<<"NO"<<endl;
else cout<<maxv<<endl;
}
return 0;
}
C
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,pos,ans=0;
int a[300005],b[300005],dp[300005];
map<int,int> m;
map<int,int> m2;
bool cmp(int x,int y)
{
return x>y;
}
signed main()
{
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>a[i];
m[a[i]]++;
}
sort(a+1,a+n+1,cmp);
for (int i=1;i<=n;i++)
{
if (a[i]!=a[i-1]) b[++pos]=a[i];
}
n=pos;
for (int i=1;i<=n;i++)
{
if (b[i]&1) dp[i]=m[b[i]]*b[i],m2[b[i]]+=dp[i];
else dp[i]=m2[(b[i]/2)*3]+b[i]*m[b[i]],m2[b[i]]+=dp[i];
}
for (int i=1;i<=n;i++) ans=max(ans,dp[i]);
cout<<ans<<endl;
return 0;
}