@lawk97
2016-12-09T10:54:05.000000Z
字数 18790
阅读 1372
(2016.11.28-2016.12.04)
作业
[CodeForces - 472A]
One way to create a task is to learn from math. You can generate some
random math statement or modify some theorems to get something new and
build a new task from that.For example, there is a statement called the "Goldbach's conjecture".
It says: "each even number no less than four can be expressed as the
sum of two primes". Let's modify it. How about a statement like that:
"each integer no less than 12 can be expressed as the sum of two
composite numbers." Not like the Goldbach's conjecture, I can prove
this theorem.You are given an integer n no less than 12, express it as a sum of two
composite numbers.
Input
The only line contains an integer n (12 ≤ n ≤ 106).
Output
Output two composite integers x and y (1 < x, y < n) such that
x + y = n. If there are multiple solutions, you can output any of
them.
题意
简单的说,就是题目告诉我们一个定理:任意一个不小于于12的整数,都可以分解为两个非素数的和。
然后给出一个不小于12的整数,求出它可以是哪两个非素数的和。如果有多种解,任意一种皆可。
思路
考虑到末位数为0,2,4,5,6,8,且大于等于10的任一数皆为非素数,则可以将给出的数分解为以上这种非素数和另一个非素数的形式。
可发现大于等于20的所有数皆可以以上述方式分解。小于20的几个数则单独讨论,以判断是归纳至上述情况一起处理,还是作为特例单独处理。
代码
#include <cstdio>
#define N 10
int main()
{
int n,a,x=0,y=0;
while(~scanf("%d",&n))
{
a=n%10;
switch (a) {
case 0:
x=4;
break;
case 1:
x=6;
break;
case 2:
x=4;
break;
case 3:
if(n<20)
x=4;
else
x=8;
break;
case 4:
x=4;
break;
case 5:
if(n<20)
x=6;
else
x=10;
break;
case 6:
x=4;
break;
case 7:
if(n<20)
x=8;
else
x=12;
break;
case 8:
x=4;
break;
case 9:
x=4;
break;
default:
break;
}
y=n-x;
if(x>y)
printf("%d %d\n",y,x);
else
printf("%d %d\n",x,y);
}
return 0;
}
[CodeForces 472B]
One way to create a task is to learn from life. You can choose some
experience in real life, formalize it and then you will get a new
task.Let's think about a scene in real life: there are lots of people
waiting in front of the elevator, each person wants to go to a certain
floor. We can formalize it in the following way. We have n people
standing on the first floor, the i-th person wants to go to the fi-th
floor. Unfortunately, there is only one elevator and its capacity
equal to k (that is at most k people can use it simultaneously).
Initially the elevator is located on the first floor. The elevator
needs |a - b| seconds to move from the a-th floor to the b-th floor
(we don't count the time the people need to get on and off the
elevator).What is the minimal number of seconds that is needed to transport all
the people to the corresponding floors and then return the elevator to
the first floor?
Input
The first line contains two integers n and k (1 ≤ n, k ≤ 2000) — the
number of people and the maximal capacity of the elevator.The next line contains n integers: f1, f2, ..., fn (2 ≤ fi ≤ 2000),
where fi denotes the target floor of the i-th person.
Output
Output a single integer — the minimal time needed to achieve the goal.
题意
有一个可以容纳k个人的电梯,要将n个人分别运送到目标楼层。由于电梯容量的限制,可能要分多次运送。电梯每上升一层或下降一层,耗时一个时间单位;乘客的出入过程耗时忽略不计。已知电梯当前在第一层,且知道n个乘客各自的目标楼层,要求全部乘客抵达目标楼层后,电梯返回第一层。求总过程的最少耗时。
思路
每一个目标楼层都要达到至少一次,且在每次上升的过程中,在沿途可以放下目标楼层相对较低的乘客。因此为节省时间,可以考虑贪心算法,从高到低地安排运输路线。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
int n,k,sum=0;
int a[2005];
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
while(1)
{
if(n<=0)
break;
sum+=2*(a[n-1]-1);
n-=k;
}
printf("%d\n",sum);
return 0;
}
[CodeForces 472C]
A way to make a new task is to make it nondeterministic or
probabilistic. For example, the hard task of Topcoder SRM 595,
Constellation, is the probabilistic version of a convex hull.Let's try to make a new task. Firstly we will use the following task.
There are n people, sort them by their name. It is just an ordinary
sorting problem, but we can make it more interesting by adding
nondeterministic element. There are n people, each person will use
either his/her first name or last name as a handle. Can the
lexicographical order of the handles be exactly equal to the given
permutation p?More formally, if we denote the handle of the i-th person as hi, then
the following condition must hold: .
Input
The first line contains an integer n (1 ≤ n ≤ 105) — the number of
people.The next n lines each contains two strings. The i-th line contains
strings fi and si (1 ≤ |fi|, |si| ≤ 50) — the first name and last name
of the i-th person. Each string consists only of lowercase English
letters. All of the given 2n strings will be distinct.The next line contains n distinct integers: p1, p2, ..., pn (1 ≤ pi ≤ n).
Output
If it is possible, output "YES", otherwise output "NO".
题意
对n个人进行排序。排序的规则如下:对于每一个人,既可以依据他的姓氏(last name),也可以根据他的名字(first name)作为排序依据来进行排序。要求排在前面的人,其参与排序的排序依据,字典序必须比排在后面的小。按照排序后的新次序从前往后,依次给出排序后队列中这n个人,各自的初始位置。求判断这种排序是否可行。
思路
既然要求每一个排在前面的人的排序依据,都要比排在后面的人的排序依据的字典序小,那么自然可以想到要让每一个人在参与排序时,其排序依据尽可能取小,这样子后面排序成功的可能性便更大。也就是采用贪心算法。可以考虑使用compare函数来比较字典序。
代码
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <iostream>
using namespace std;
int n,flag=1;
char f[100005][55],s[100005][55];
string a,b,now;
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s %s",f[i],s[i]);
}
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
a=f[x-1];
b=s[x-1];
if(i==0)
{
if(a.compare(b)<0)
now=a;
else
now=b;
}
else
{
if(now.compare(a)>=0&&now.compare(b)>=0)
{
flag=0;
break;
}
else if(now.compare(a)>=0&&now.compare(b)<0)
{
now=b;
}
else if(now.compare(a)<0&&now.compare(b)>=0)
{
now=a;
}
else if(now.compare(a)<0&&now.compare(b)<0)
{
if(a.compare(b)<0)
now=a;
else
now=b;
}
}
}
if(flag)
printf("YES\n");
else
printf("NO\n");
return 0;
}
[CodeForces 471A]
Two polar bears Menshykov and Uslada from the St.Petersburg zoo and
elephant Horace from the Kiev zoo got six sticks to play with and
assess the animals' creativity. Menshykov, Uslada and Horace decided
to make either an elephant or a bear from those sticks. They can make
an animal from sticks in the following way:Four sticks represent the animal's legs, these sticks should have the
same length. Two remaining sticks represent the animal's head and
body. The bear's head stick must be shorter than the body stick. The
elephant, however, has a long trunk, so his head stick must be as long
as the body stick. Note that there are no limits on the relations
between the leg sticks and the head and body sticks. Your task is to
find out which animal can be made from the given stick set. The zoo
keeper wants the sticks back after the game, so they must never be
broken, even bears understand it.
Input
The single line contains six space-separated integers li (1 ≤ li ≤ 9)
— the lengths of the six sticks. It is guaranteed that the input is
such that you cannot make both animals from the sticks.
Output
If you can make a bear from the given set, print string "Bear"
(without the quotes). If you can make an elephant, print string
"Elephant" (wıthout the quotes). If you can make neither a bear nor an
elephant, print string "Alien" (without the quotes).
题意
用六根木棒来拼接图像。要有四根等长的木棒做腿,剩下的两根木棒,不等长的话话可以做熊的头和鼻子,等长的话可以做大象的头和鼻子。已知六根木棒的长度,且明白一定无法同时拼出大象或者熊。判断拼接的情况。
思路
排序之后很容易找到四个相等的木棍。然后判断剩下的两个木棍的大小关系即得结果。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
int x,i;
int a[6];
for(int i=0;i<6;i++)
{
scanf("%d",&a[i]);
}
sort(a,a+6);
for(i=0;i<3;i++)
{
if(a[i]==a[i+1]&&a[i]==a[i+2]&&a[i]==a[i+3])
{
a[i]=a[i+1]=a[i+2]=a[i+3]=-1;
break;
}
}
if(i==3)
printf("Alien\n");
else
{
sort(a,a+6);
if(a[4]==a[5])
printf("Elephant\n");
else
printf("Bear\n");
}
return 0;
}
[CodeForces - 471B]
It's time polar bears Menshykov and Uslada from the zoo of St.
Petersburg and elephant Horace from the zoo of Kiev got down to
business. In total, there are n tasks for the day and each animal
should do each of these tasks. For each task, they have evaluated its
difficulty. Also animals decided to do the tasks in order of their
difficulty. Unfortunately, some tasks can have the same difficulty, so
the order in which one can perform the tasks may vary.Menshykov, Uslada and Horace ask you to deal with this nuisance and
come up with individual plans for each of them. The plan is a sequence
describing the order in which an animal should do all the n tasks.
Besides, each of them wants to have its own unique plan. Therefore
three plans must form three different sequences. You are to find the
required plans, or otherwise deliver the sad news to them by stating
that it is impossible to come up with three distinct plans for the
given tasks.
Input
The first line contains integer n (1 ≤ n ≤ 2000) — the number of
tasks. The second line contains n integers h1, h2, ..., hn
(1 ≤ hi ≤ 2000), where hi is the difficulty of the i-th task. The
larger number hi is, the more difficult the i-th task is.
Output
In the first line print "YES" (without the quotes), if it is possible
to come up with three distinct plans of doing the tasks. Otherwise
print in the first line "NO" (without the quotes). If three desired
plans do exist, print in the second line n distinct integers that
represent the numbers of the tasks in the order they are done
according to the first plan. In the third and fourth line print two
remaining plans in the same form.If there are multiple possible answers, you can print any of them.
题意
给出一些任务,这些任务的困难度可能相同,可能不同。根据困难程度,将这些任务从小到大排列,看能否有至少三种排列方式。如果能,输出任意三种。
思路
排序后,从前往后遍历,若满足以下两种情况之一即证明可以:
1,有至少三个连续的任务困难程度相等,则这三个任务的排列方式即有3!=6种;
2,有至少先后两组,每组两个连续的任务困难程度相等,则这两组共四个任务的排列方式为2*2!=4种。
如果可以的话,输出每种方法时对应地交换那几个任务的次序即可。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct task
{
int o,d;
}a[2005];
int n,ans=1;
task t1,t2,t3;
int cmp(task a,task b)
{
return a.d<b.d;
}
void pri()
{
printf("%d",a[0].o);
for(int j=1;j<n;j++)
{
printf(" %d",a[j].o);
}
printf("\n");
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
a[i].o=i+1;
scanf("%d",&a[i].d);
}
sort(a,a+n,cmp);
for(int i=0;i<n;i++)
{
if( (i+1<n&&a[i].d==a[i+1].d)
&& (i+2<n&&a[i].d==a[i+2].d) )
{
printf("YES\n");
pri();
t1=a[i],t2=a[i+1],t3=a[i+2];
a[i]=t2,a[i+1]=t1;
pri();
a[i]=t1,a[i+1]=t2;
a[i]=t3,a[i+2]=t1;
pri();
return 0;
}
if( (i+1<n&&a[i].d==a[i+1].d)
&& (i+2<n&&a[i].d!=a[i+2].d) )
{
for(int j=i+2;j<n;j++)
{
if(j+1<n&&a[j].d==a[j+1].d)
{
printf("YES\n");
pri();
t1=a[i],t2=a[i+1];
a[i]=t2,a[i+1]=t1;
pri();
a[i]=t1,a[i+1]=t2;
t1=a[j],t2=a[j+1];
a[j]=t2,a[j+1]=t1;
pri();
return 0;
}
}
break;
}
}
printf("NO\n");
return 0;
}
[CodeForces - 471C]
Polar bears Menshykov and Uslada from the zoo of St. Petersburg and
elephant Horace from the zoo of Kiev decided to build a house of
cards. For that they've already found a hefty deck of n playing cards.
Let's describe the house they want to make:The house consists of some non-zero number of floors. Each floor
consists of a non-zero number of rooms and the ceiling. A room is two
cards that are leaned towards each other. The rooms are made in a row,
each two adjoining rooms share a ceiling made by another card. Each
floor besides for the lowest one should contain less rooms than the
floor below. Please note that the house may end by the floor with more
than one room, and in this case they also must be covered by the
ceiling. Also, the number of rooms on the adjoining floors doesn't
have to differ by one, the difference may be more.While bears are practicing to put cards, Horace tries to figure out
how many floors their house should consist of. The height of the house
is the number of floors in it. It is possible that you can make a lot
of different houses of different heights out of n cards. It seems that
the elephant cannot solve this problem and he asks you to count the
number of the distinct heights of the houses that they can make using
exactly n cards.
Input
The single line contains integer n (1 ≤ n ≤ 1012) — the number of
cards.
Output
Print the number of distinct heights that the houses made of exactly n
cards can have.
Hint
In the first sample you can build only these two houses (remember, you
must use all the cards):
Thus, 13 cards are enough only for two floor houses, so the answer is
1.The six cards in the second sample are not enough to build any house.
题意
现给出一种卡牌拼接方法。两个卡牌相对成锥形表示一个房间,某一层如果有多个房间的话,则每一个房间须至少与另一个同层的房间相邻,且需要用一张卡牌连接两个锥尖处来表示天花板。在天花板上面可以用同样的规则拼接更高一层。要注意更高层的房间数必然小于低一层的房间数。同时要求所有卡牌都需要使用。
现给出卡牌数目n,求出可能拼出的楼层的高度有多少种。如果不可能拼出楼,则为0种。
思路
多画几种情况即可发现i层高的楼(i >= 1),需要的最少卡牌数为i*(3*i+1)/2。同时容易发现,任意卡牌数如果想拼出i层高的楼,只需要满足(n-2*i)%3==0即可。原因很简单,每层楼的卡牌数都是2+3*k的形式,只要卡牌数减去2*i之后剩下的数目,是3的倍数,那么至少可以全部放到第一层。如果减去2*i之后剩下的不是3的倍数,那么显然会有几张牌无法处理。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
using namespace std;
int main()
{
long long n;
int ans=0;
scanf("%lld",&n);
for(long long i=1;i*(3*i+1)/2<=n;i++)
{
if((n-2*i)%3==0)
ans++;
}
printf("%d\n",ans);
return 0;
}
[CodeForces - 467A]
George has recently entered the BSUCP (Berland State University for
Cool Programmers). George has a friend Alex who has also entered the
university. Now they are moving into a dormitory.George and Alex want to live in the same room. The dormitory has n
rooms in total. At the moment the i-th room has pi people living in it
and the room can accommodate qi people in total (pi ≤ qi). Your task
is to count how many rooms has free place for both George and Alex.
Input
The first line contains a single integer n (1 ≤ n ≤ 100) — the number
of rooms.The i-th of the next n lines contains two integers pi and qi
(0 ≤ pi ≤ qi ≤ 100) — the number of people who already live in the
i-th room and the room's capacity.
Output
Print a single integer — the number of rooms where George and Alex can
move in.
题意
有n个房间,给出每个房间的可容纳人数和已有人数,求有多少个房间可以供两位新同学一起入住。
思路
每个房间可容纳人数减去已有人数,如果值大于等于2,则为可以。统计有多少件可以即可。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
int n,x,y,sum=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&x,&y);
if(y-x>=2)
sum++;
}
printf("%d\n",sum);
return 0;
}
[CodeForces - 467B]
After you had helped George and Alex to move in the dorm, they went to
help their friend Fedor play a new computer game «Call of Soldiers 3».The game has (m + 1) players and n types of soldiers in total. Players
«Call of Soldiers 3» are numbered form 1 to (m + 1). Types of soldiers
are numbered from 0 to n - 1. Each player has an army. Army of the
i-th player can be described by non-negative integer xi. Consider
binary representation of xi: if the j-th bit of number xi equal to
one, then the army of the i-th player has soldiers of the j-th type.Fedor is the (m + 1)-th player of the game. He assume that two players
can become friends if their armies differ in at most k types of
soldiers (in other words, binary representations of the corresponding
numbers differ in at most k bits). Help Fedor and count how many
players can become his friends.
Input
The first line contains three integers n, m, k (1 ≤ k ≤ n ≤ 20;
1 ≤ m ≤ 1000).The i-th of the next (m + 1) lines contains a single integer xi
(1 ≤ xi ≤ 2n - 1), that describes the i-th player's army. We remind
you that Fedor is the (m + 1)-th player.
Output
Print a single integer — the number of Fedor's potential friends.
题意
有m+1个玩家,有n种军队。用十进制数Xi来表示第i个玩家(1<=i<=m+1)拥有的军队种类,表示规则如下:Xi转化成二进制后,第j位为1即表示该玩家拥有第j种军队,为0即表示该玩家没有第j种军队(0<=j<=n-1)。
任意两个玩家,如果不同时拥有的军队种数小于等于k,则认为这两个玩家可以成为朋友。求可以和第m+1个玩家成为朋友的其他玩家的数目。
思路
既然Xi表示的是第i个玩家拥有的军队种类,那么依据xor每一位相同则结果中该位为0,不相同则该位为1的用法,可以用Xi ^ X(m+1) 来表示第i个玩家与第m+1个玩家两人拥有的军队种类的对比情况。然后统计该值转化成二进制后,有多少位为1,这个数目如果小于等于k,则说明第i个玩家(1<=i<=m)可以和第m+1个玩家成为朋友。统计可以和第m+1个玩家成为朋友的玩家数目即可。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
int n,m,k,ans=0;
int a[1005];
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<=m;i++)
scanf("%d",&a[i]);
for(int i=0;i<m;i++)
{
int ha=a[m]^a[i];
int sum=0;
while(ha>0)
{
sum+=(ha&1);
ha=ha>>1;
}
if(sum<=k)
ans++;
}
printf("%d\n",ans);
return 0;
}
[CodeForces - 467C]
The new ITone 6 has been released recently and George got really keen
to buy it. Unfortunately, he didn't have enough money, so George was
going to work as a programmer. Now he faced the following problem at
the work.Given a sequence of n integers p1, p2, ..., pn. You are to choose k
pairs of integers:[l1, r1], [l2, r2], ..., [lk, rk]
(1 ≤ l1 ≤ r1 < l2 ≤ r2 < ... < lk ≤ rk ≤ n; ri - li + 1 = m), in such
a way that the value of sum is maximal possible. Help George to cope
with the task.
Input
The first line contains three integers n, m and k
(1 ≤ (m × k) ≤ n ≤ 5000). The second line contains n integers
p1, p2, ..., pn (0 ≤ pi ≤ 109).
Output
Print an integer in a single line — the maximum possible value of sum.
题意
从一个有n个数的数列中,取k部分。每一部分最右边的数的位置,比该部分最左边的数的位置大m-1(m>=1)。找出一种取法,使得取出的所有数的和最大。
思路
用二维数组来处理动态规划。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
int n,m,k;
long long ans=0;
long long a[5005],b[5005],v[5005][5005];
int main()
{
scanf("%d%d%d",&n,&m,&k);
scanf("%lld",&a[1]);
for(int i=2;i<=n;i++)
{
int x;
scanf("%d",&x);
a[i]=a[i-1]+x;
}
b[m]=a[m];
for(int i=m;i<=n;i++)
b[i]=a[i]-a[i-m];
memset(v, 0, sizeof(0));
for(int i=1;i<=k;i++)
{
long long xmax=0;
for(int j=i*m;j<=n;j++)
{
xmax=max( v[i-1][j-m]+b[j],xmax);
v[i][j]=xmax;
}
}
printf("%lld\n",v[k][n]);
return 0;
}
[CodeForces - 466A]
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?
Input
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.
Output
Print a single integer — the minimum sum in rubles that Ann will need
to spend.
题意
地铁有两种购票方式,一种是单程地铁票a卢布一张;另一种是特价票b卢布一张,可以使用m次。现在计划乘坐地铁n次,求花费最少的方案的花费。
思路
简单的两种思路。一种是分类讨论,将可能的乘坐方案分成几大类,根据abmn的值得出结果;另一种是直接根据购买的特价票的票数,从0到n/m+1进行遍历,找出花费最少的方案。前者效率高,但是容易疏漏;后者效率略低,但是编程较简便。
代码1
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
int n,m,a,b,sum=0;
scanf("%d%d%d%d",&n,&m,&a,&b);
if(m>=n)
{
sum=n*a<b?n*a:b;
}
else
{
if(a<=1.0*b/m)
sum=n*a;
else
{
sum+=(n/m*b);
sum+= (n-n/m*m)*a < b ? (n-n/m*m)*a : b;
}
}
printf("%d\n",sum);
return 0;
}
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
using namespace std;
int n,m,a,b;
int main()
{
scanf("%d%d%d%d",&n,&m,&a,&b);
int sum,ans=n*a;
for(int i=0;i<=n/m+1;i++)
{
if(n>=i*m)
sum=i*b+(n-i*m)*a;
else
sum=i*b;
ans=ans<=sum?ans:sum;
}
printf("%d\n",ans);
return 0;
}
[CodeForces - 466B]
The start of the new academic year brought about the problem of
accommodation students into dormitories. One of such dormitories has a
a × b square meter wonder room. The caretaker wants to accommodate
exactly n students there. But the law says that there must be at least
6 square meters per student in a room (that is, the room for n
students must have the area of at least 6n square meters). The
caretaker can enlarge any (possibly both) side of the room by an
arbitrary positive integer of meters. Help him change the room so as
all n students could live in it and the total area of the room was as
small as possible.
Input
The first line contains three space-separated integers n, a and b
(1 ≤ n, a, b ≤ 10^9) — the number of students and the sizes of the
room.
Output
Print three integers s, a1 and b1 (a ≤ a1; b ≤ b1) — the final area of
the room and its sizes. If there are multiple optimal solutions, print
any of them.
题意
现有一个高不可变动,底面为a*b的长方形的房间。现要在这个房间内安置n个学生,要求房间的面积必须大于等于6*n。因此我们可能要对房间进行扩建,当然也可能不用。如果要扩建的话,扩建方式是将长或宽或两者都增大不定的正整数长度。求出满足要求之后的房间的最小面积和对应的长和宽。
思路
找出宽。以宽的初始值做为起点,以(6*n)^0.5 +1 作为终点,依次遍历。通过假设一个边的长度已经确定,求出另一个对应的边,并不断比较对应的面积,来找出最小的面积和对应的两边长度。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
using namespace std;
int main()
{
long long flag=0,a,b,b1,n,xm;
long long aa,bb,ans=1000000000000000000;
scanf("%lld%lld%lld",&n,&a,&b);
aa=a;
bb=b;
n*=6;
if(a*b>=n)
ans=a*b;
if(a>b)
{
flag=1;
swap(a, b);
}
xm=ceil(sqrt(n));
for(long long i=a;i<=xm;i++)
{
if(b*i>=ans)
break;
b1=ceil(1.0*n/i);
b1=b1>b?b1:b;
if(i*b1<ans)
{
aa=i;
bb=b1;
ans=i*b1;
}
}
if(flag)
swap(aa, bb);
printf("%lld\n%lld %lld\n",ans,aa,bb);
return 0;
}
[CodeForces - 466C]
You've got array a[ 1 ], a[ 2 ], ..., a[n], consisting of n integers.
Count the number of ways to split all the elements of the array into
three contiguous parts so that the sum of elements in each part is the
same.More formally, you need to find the number of such pairs of indices
i, j (2 ≤ i ≤ j ≤ n - 1), that .
Input
The first line contains integer n (1 ≤ n ≤ 5·105), showing how many
numbers are in the array. The second line contains n integers a1,
a2, ..., a[n] (|a[i]| ≤ 109) — the elements of array a.
Output
Print a single integer — the number of ways to split the array into
three parts with the same sum.
题意
给出一列数,欲将这列数分割为其和相等的三部分,求有多少种分割方式。
思路
易知只有每个部分的和都为总和的三分之一时,才可符合题意。
那么从第一个数到第一部分最后一个数之间的所有数的和即为总数的三分之一,从第一个数到第二部分最后一个数之间的所有数的和即为总数的三分之二。
且第二部分的最后一个数必须在总序列的最后一个数之前,才能保证存在第三个部分;第二部分的第一个数必须在总序列的第一个数之后,才能保证存在第一个部分。
那么取一个标记数s和一个标记数ans,令两数初始值皆为0。从位置0到位置n-2依次遍历,发现符合第一部分最后一个数的条件的数就s++,发现符合第二部分最后一个数的条件的数就ans+=s。由于初始s=0,那么即使搜到某个数符合第二部分最后一个数的条件,要执行ans+=s,但在此之前,还未发现可做第一部分最后一个数的数(即搜到的“第二部分尾数”只能属于第一部分的情况),那么此时由于s==0,ans+=0也不会造成错误。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
long long a,sum[1000000];
long long n,s=0,ans=0;
int main()
{
scanf("%lld",&n);
for(long long i=0;i<n;i++)
{
scanf("%lld",&a);
if(i==0)
{
sum[i]=a;
continue;
}
sum[i]=sum[i-1]+a;
}
if(sum[n-1]%3==0)
{
for(long long i=0;i<n-1;i++)
{
if(sum[i]==1.0*sum[n-1]/3*2)
ans+=s;
if(sum[i]==1.0*sum[n-1]/3)
s++;
}
}
printf("%lld\n",ans);
return 0;
}