Ann has recently started commuting by subway. We know that a one ride subway ticket costs a rubles. Besides, Ann found out that she can buy a special ticket for m rides (she can buy it several times). It costs b rubles. Ann did the math; she will need to use subway n times. Help Ann, tell her what is the minimum sum of money she will have to spend to make n rides?
The single line contains four space-separated integers n, m, a, b (1 ≤ n, m, a, b ≤ 1000) — the number of rides Ann has planned, the number of rides covered by the m ride ticket, the price of a one ride ticket and the price of an m ride ticket.
Print a single integer — the minimum sum in rubles that Ann will need to spend.
6 2 1 2
6
5 2 2 3
8
In the first sample one of the optimal solutions is: each time buy a one ride ticket. There are other optimal solutions. For example, buy threem ride tickets.
题意:Ann要乘坐n次地铁,现在有两种票,一种是b元m次,一种是一次a元,求最少花费多少
思路:这题目意思很简单,但是一些特殊数据不是这个过不了就是那个过不了,代码改来改去最后还是错了,主要原因是思路不清晰,逻辑混乱
这题正确的思路:如果b/m>a的话直接输出n*a,否则n/m算出第二种票最多可以买多少张,然后拿n*a和n/m*b+n%m*a相比较哪个小,如果只是这样的话还是wa,还有一种情况就是你n%m*a>1*b,也就是说再多买一张m票可能花费的更少,因此还需要比较这种情况
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int main()
{
int n,m,a,b;
cin>>n>>m>>a>>b;
if(b/m > a) cout<<n*a<<endl;
else {
int cent = n/m;
int ans = min(min(cent*b + n%m*a,n*a),(cent+1)*b);
cout<<ans<<endl;
}
return 0;
}
思路:题目n=10^9,如果直接枚举o(n),会TLE,但是我们考虑到6n最大不超过6*10^9,也就是说a*b最大不超过6*10^9,那么我们假设一开始a<b的话,那么我们只需要枚举a------a+sqrt(6*n),o(sqrt(n))的时间可以过
开始就假设a<b这样可以不用分类讨论,用flag标记一下,最后swap一下就行
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long LL;
int main()
{
LL n,a,b;
int flag = 0;
LL a1,b1;
cin>>n>>a>>b;
if(a > b)
{
swap(a,b);
flag = 1;
}
LL sum = 6*n;
LL INF = 1LL<<62;
for(LL i = a; i <= a + 50000LL; i++)
{
LL tb = sum/i + (sum%i != 0);//如果不能整除的话b1的值要加1,否则b1*a<sum
tb = max((LL)b,tb);
LL mins = tb * i;
if(mins < INF)
{
INF = mins;
a1 = i;
b1 =tb;
}
}
if(flag) swap(a1,b1);
cout<<INF<<endl;
cout<<a1<<" "<<b1<<endl;
return 0;
}
思路:因为是连续的,因此把每个位置求和,首先判断总和是否能被3整出,如果不能直接输出0,否则找出sum[i]=sum[n]/3*2之前总共出现过多少次sum[i] = sum[n]/3,因为有多少个sum[n]/3就有多少种,例如:1 2 0 3 3 sum[4] = 6 = sum[n]/3*2,它前面有两个sum[i] = sum[n]/3,120 3 3或者12 03 3,看出来了没有?有n个sum[n]/3就代表有n-1个块加起来是0,那么放左边放右边都不影响
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long LL;
const int Max = 5*100000+10;
LL sum[Max];
int main()
{
int n,a;
cin>>n;
sum[0] = 0;
for(int i = 1; i <= n; i++)
{
cin>>a;
sum[i] =sum[i-1] + a;
}
if(sum[n]%3)
{
cout<<0<<endl;
}
else
{
LL one = sum[n]/3,two = one*2,cent = 0,ans = 0;
for(int i = 1; i < n ; i++)//i到N-1就行了
{
if(sum[i] == two)//有一点要注意这个判断必须放在前面,因为有可能one = two ,如果先cent++再加的话会多算
{
ans += cent;
}
if(sum[i] == one)
{
cent++;
}
}
cout<<ans<<endl;
}
return 0;
}