var
a,b:int64;
begin
readln(a,b);
writeln(a*b div 2);
end.
var
k,n,i,j,x,y:longint;
begin
readln(k);
for i:=1 to k do
begin
readln(n);
readln(x);
for j:=1 to n do
read(y);
if x=0 then writeln('kqp') else writeln('czy');
end;
end.
最近备受关注的人机大战——谷歌机器人AlphaGo对战围棋大师李世石。经过五盘的对决,最终AlphaGo以4:1战胜李世石,并且使得它的排名一举上升为世界第二,仅次于中国选手柯洁。为了准备迎接柯洁的挑战,必须让AlphaGo提升自身的处理能力,但由于时间有限,仅能临时采购一些性能不一的处理器,现在知道每种处理器的处理能力和发热量,由于机器过热可能会导致AlphaGo程序崩溃,必须要控制好它的最大发热量才行,这个艰巨的任务落在你的头上,必须选出一些处理器来尽可能的提供最强的处理能力。
input
第一行两个正整数n,t,表示可选择的处理器种类和最大发热量,注意,每种处理器可以采购多个,
接下来n行,每行两个正整数,分别表示每种处理器的处理能力和发热量(数值均小于100)
output
一行,一个正整数,表示AlphaGo的最大处理能力
Sample Input
3 5
2 2
4 3
1 5
Sample Output
6
HINT
50% 数据 n<=30
100% 数据 n<=300,t<=10000
这道题目其实就是一个背包问题,因为每个处理器可以采购多个,所以是完全背包问题,在这里不多讲,不会的去翻翻资料吧。
代码:
var
f:array[0..10000] of Longint;
w,v:array[1..300] of Longint;
n,t,i,j:longint;
begin
readln(n,t);
for i:=1 to n do
readln(w[i],v[i]);
for i:=1 to n do
for j:=v[i] to t do
if f[j-v[i]]+w[i]>f[j] then f[j]:=f[j-v[i]]+w[i];
writeln(f[t]);
end.
测试点 |
n |
1 |
n = 10 |
2 |
n = 100 |
3 |
n = 1000 |
4 |
n = 200000 |
5 |
n = 200000 |
6 |
n = 1000000 |
7 |
n = 1000000 |
8 |
n = 1000000 |
9 |
n = 1000000 |
10 |
n = 1000000 |
var
flag:boolean;
f:array[0..1000000] of Longint;
a:array[1..1000000] of Longint;
n,i,j,k,sum,l,r,mid:longint;
begin
readln(n);
for i:=1 to n do
begin
read(a[i]);
inc(sum,a[i]);
f[i]:=f[i-1]+a[i];
end;
for i:=n downto 1 do
begin
if sum mod i<>0 then continue; //这里同样也可以加一个与下面方法相同的优化。
k:=sum div i;
flag:=true;
l:=1;
for j:=1 to i do //依次判断i组是否可以组成.
begin
r:=n;
while l<=r do
begin
mid:=(l+r) div 2;
if f[mid]=k then break;
if f[mid]>=k then r:=mid-1 else l:=mid+1;
end; //二分是找当前这一组的和是否能组成.
if f[mid]<>k then
begin
flag:=false;
break;
end;
inc(k,sum div i); //能组成就下一组,同时更新要找的数以及上限l.
l:=mid+1;
end;
if flag then break; //如果这i组都可以组成则直接break.
end;
if flag then writeln(sum div i) else writeln(sum);
end.
var
i,j,n,tot,sum,s,max:longint;
a:array[0..1000000] of longint;
begin
readln(n);
for i:=1 to n do
begin
read(a[i]);
inc(sum,a[i]);
if a[i]>max then max:=a[i];
end;
for i:=n downto 1 do
begin
if (sum mod i<>0) or (sum div ithen continue; //这里就是优化和pd
s:=sum div i;
tot:=0;
for j:=1 to n do
begin
inc(tot,a[j]);
if tot>s then break;
if tot=s then tot:=0;
end; //这里直接模拟.
if tot=0 then break;
end;
if tot=0 then writeln(s) else writeln(sum);
end.
Sample Input
4 4
1 4
3 4
2 3
1 4
Sample Output
3
HINT
50%数据保证1≤n,m≤1000,答案小于等于1000
100%数据保证1≤n,m≤500000,答案小于等于2^31-1
这道题目考试时没捞到1分,就是因为读题不仔细,当然也有一部分题目描述不完整的情况,但是,为什么其他人能明白,归根到底还是自身的问题,已经说了是多少轮操作之后才会得到原来的序列,一轮操作——必定是完整的一轮,不然怎么叫一轮操作,那就叫一些操作。
所以这题用模拟的方法可以拿到50分,但是我们可以进一步优化。
我们先用数据来模拟交换的一轮:
1 2 3 4
4 2 3 1
4 2 1 3
4 1 2 3
3 1 2 4
我们可以留下一轮繁琐操作的本质,也就是1个位置换来换去,到底换到了哪儿。
f[1]=1,2
f[2]=2,3
f[3]=3,1
f[4]=4,4
f[i]表示的是第i个位置一轮操作之后换到了f[i]这个位置。
我们可以发现4他是不换的,所以4要回到原来的位置只用1次。而1,2,3可以发现他们是组成了一个循环
1-2-3-1,所以1,2,3回到原来的位置只用3次,他们的最小公倍数gbs(1,3)=3,所以答案=3
再举一个栗子:
5 3
1 2
2 3
4 5
交换一轮:
1 2 3 4 5
2 1 3 4 5
2 3 1 4 5
2 3 1 5 4
f[1]=1,3
f[2]=2,1
f[3]=3,2
f[4]=4,5
f[5]=5,4
1,2,3组成了一个循环1-3-2-1
4,5组成了一个循环4-5-4
1,2,3用3次,4,5用2次,gbs(3,2)=6
从这里我们就可以发现,其实我们只要看f数组组成了多少个循环,然后求出n个循环个数的公倍数即可。
代码:
type
arr=array[1..500000] of int64;
var
a:arr;
f:Array[1..500000,0..1] of longint;
x,y:Array[1..500000] of Longint;
bz:array[1..500000] of boolean;
n,m,ans,answer,t,tot:int64;
i,j:Longint;
function gcd(x,y:int64):int64; //求出gbs——公倍数.
var
z,xx,yy:int64;
begin
xx:=x; yy:=y;
while x mod y<>0 do
begin
z:=x mod y;
x:=y;
y:=z;
end;
exit(xx*yy div y);
end;
procedure sort(l,r:Longint); //快排用于方便模拟.
var
i,j,mid,p:longint;
begin
i:=l; j:=r;
mid:=f[(i+j) div 2,0];
while ido
begin
while f[i,0]do inc(i);
while f[j,0]>mid do dec(j);
if i<=j then
begin
p:=f[i,0]; f[i,0]:=f[j,0]; f[j,0]:=p;
p:=f[i,1]; f[i,1]:=f[j,1]; f[j,1]:=p;
inc(i); dec(j);
end;
end;
if lthen sort(l,j);
if ithen sort(i,r);
end;
begin
readln(n,m);
for i:=1 to m do readln(x[i],y[i]);
for i:=1 to n do a[i]:=i;
for i:=1 to m do
begin
t:=a[x[i]]; a[x[i]]:=a[y[i]]; a[y[i]]:=t; //交换一轮后的根本.
end;
for i:=1 to n do
begin
f[i,0]:=a[i];
f[i,1]:=i;
end; //判断出第i个位置到底是换到了哪里,表示为f[i,1].
sort(1,n);
fillchar(bz,sizeof(bz),true);
answer:=1;
for i:=1 to n do
if bz[i] then //优化——已经有在循环里的数,无需再次判断。
begin
j:=f[i,1];
ans:=1;
while j<>i do //while 循环用于找当前第i个数是在哪个循环,ans用来记录这个循环每个数要回到自己位置的个数.
begin
bz[j]:=false;
j:=f[j,1];
inc(ans);
end;
answer:=gcd(answer,ans);
end;
writeln(answer);
end.