咳咳。
题目链接:https://www.nowcoder.com/acm/contest/143/A
题意:给s和c数组,每个数组各有n个数,要求去掉k个s[i]和c[i],要尽量让大,求删掉k个后上述式子的最大值。
题解:第一次见到二分凑答案的题。
我们假设>=d,移项后可以得出∑s[i](c[i]-d)>=0这个式子,我们令a[i] = s[i]*(c[i]-d),然后对a数组进行排序,那么a的前k个会较小,而后n-k项的和就是∑s[i](c[i]-d)>=0,这时候可以二分答案。记后n-k项和为sum,如果sum>=0,那么说明d偏小了,反之d偏大。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
inline void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,k,s[maxn],c[maxn],Max,m;
double a[maxn];
bool judge()
{
double sum = 0;
for(int i=k;i=0)
return true;
return false;
}
int main()
{
read(n),read(k);
for(int i=0;ieps)
{
double mid = (l+r)/2;
for(int i=0;i
题目链接:https://www.nowcoder.com/acm/contest/143/G
题意:给一个数c和n,要求从1-n中找一对(a,b),使得其最大公约数为c,并尽量使a*b的结果大,问a*b最大是多少。
题解:
以c为底不断地扩大a和b,假设最大能扩大x倍,x=n/c; 那么就把a变成c*n,b变成c*(n-1),由于gcd(c*n,c*(n-1)) = c*gcd(n,n-1) = c,所以就这么扩大了。当然特殊情况注意一下,比如说连扩大2倍都不行,a和b都得等于c。万一c>n,直接输出-1就行了。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
inline void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
inline void print(int x)
{
if(x<0){ putchar('-'); x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
ll c,n,a,b;
int main()
{
scanf("%lld%lld",&c,&n);
a = c;
b = c;
int temp = n/c;
b = temp*c;
a = (temp-1)*c;
if(temp==1)
a = b =c;
if(temp==0)
cout<<-1<
题目链接:https://www.nowcoder.com/acm/contest/143/J
题意:有n个人,2人房价格为p1,3人房价格为p2,问最少花多少钱能把人全安顿下来。
题解:看上去像一个完全背包问题,但是它的n是1e9的数据规模,而房间种类只有两个,所以不是完全背包。
一个值得注意的点就是,一个房子是可以不住满的。所以我在比赛时候想到的解法是:看全住3个人至少要多少间,假设结果为m,那么枚举[0,m],再算出此时要开的二人房的数量,枚举出最小费用。
这种做法复杂度是O(n)的,本来打算最后一个点TLE的,结果评测机跑的贼快,居然过了。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
ll n,p,q,ans;
int main()
{
cin>>n>>p>>q;
ll tot = n/3;
if(n%3!=0)
tot++;
ans = tot*q;
for(int i=0;i
底下来看看O(1)的解法。
就是先判断2人和3人间哪个性价比比较高,如果2人间比较高的话,那么就全买两人间的,如果最后多一个人的话,可以考虑减去一个两人间,开一个三人间。。三人间的解法也类似,这里就不提了。直接上隔壁奥利奥队的代码
#include
using namespace std;
typedef long long LL;
const int INF=INT_MAX;
LL n,p2,p3;
int main() {
scanf("%lld%lld%lld",&n,&p2,&p3);
LL sum=0;
if(3*p2<=2*p3){//二人间性价比高
sum=n/2*p2;//先尽可能的全是二人间
if(n%2==1 && n/2) sum+=min(p2,p3-p2);//如果多了一个,且二人间多于1间,那就可以考虑
//是加一个二人间还是减掉一个二人换一个三人
else if (n%2)sum +=min(p2,p3);//考虑只有一个人的情况
}
else{
sum=n/3*p3;
if(n%3==2) sum+=min(p2,p3);
if(n%3==1&&n/3) sum+=min(2*p2-p3,p2);//多了一个,可以少一个3人加两个2人,也可以直接加一个二人
if(n%3==1&&n/3==0) sum+=p2;//只有一个人
}
printf("%lld\n",sum);
}