您的位置:首页 > 其它

NOIP2015模拟1

2015-08-28 14:54 204 查看

传送门

http://218.62.22.209:8080/problem.php?id=3175

http://218.62.22.209:8080/problem.php?id=3176

http://218.62.22.209:8080/problem.php?id=3177

T1 相关月

题目大意

给出年份和两个月份,判断这两个月的第一天是否都是星期I,

题解

就是判断I,J两个月份之间有多少天如果是7的倍数,就是相关月

可以打表出闰年和平年的月份天数表

判断闰年的方法复习一下

1.能整除4,但不能整除100

2.能整除400

const
x:array[1..12]of longint=(31,28,31,30,31,30,31,31,30,31,30,31);
y:array[1..12]of longint=(31,29,31,30,31,30,31,31,30,31,30,31);
var
n:longint;
i,j,a,b,c,sum:longint;
procedure swap(var a,b:longint);
var c:longint;
begin
c:=a; a:=b; b:=c;
end;

begin
readln(n);
for i:=1 to n do
begin
readln(a,b,c); sum:=0;
if b>c then swap(b,c);
if ((a mod 100<>0)and(a mod 4=0))or(a mod 400=0)
then for j:=b to c-1 do inc(sum,y[j])
else for j:=b to c-1 do inc(sum,x[j]);
if sum mod 7=0
then writeln('YES')
else writeln('NO');
end;
end.


T2 无限序列

题目大意

给定一个无限序列的产生方法:初始序列为1,然后每次1变10,0变1,进行无限次操作产生无限序列,对于询问[L,R]内的1的个数,L,R<=2632^{63}

题解

我们观察一下这个无限序列的产生过程

1,10,101,10110,10110101……

我们可以发现,从第三次开始,第I次得到的序列为第I-1次的序列后接上第I-2次的序列,即斐波那契的构成方法

对于询问[L,R]可以变成f(1,R)-f(1,L-1)

最多91次就可以得到2632^{63}长度的序列了,所以我们与按操作次数处理出该串内的1的个数,对于超过的部分我们可以发现它也包含某次操作的字符串,通过截取每次已知答案的长度,直到吻合已知答案的长度

var
ans:array[0..100,1..2]of int64;
i,j,k:longint;
n:longint;
a,b,c,d,lin,linn:int64;
function f(a,b:int64):int64;
var i,tt:longint;
begin
if a=0 then exit(0);
for i:=b downto 1 do
if ans[i,1]<=a
then begin tt:=i; break; end;
f:=ans[tt,2]+f(a-ans[tt,1],tt);
end;

begin
a:=1; b:=1; c:=1; d:=2;
ans[1,1]:=1; ans[1,2]:=1; ans[2,1]:=2; ans[2,2]:=1;
for i:=3 to 91 do
begin
lin:=a+b; linn:=c+d;
ans[i,1]:=linn; ans[i,2]:=lin;
a:=b; b:=lin; c:=d; d:=linn;
end;
readln(n);
for i:=1 to n do
begin
readln(a,b);
writeln(f(b,91)-f(a-1,91));
end;
end.


T3 删数

题目大意

给定n个数,不断删除一段数,直到全删完,删除有两种方法,从左面第一个开始删到第I个,或者从右面第一个删到第I个

题解

区间DP,也就是说从左面删除一部分[1,I]再从右面删除另一部分[I+1,N],分左右DP

左面dp[1,i]=max(dp[1,i],dp[1,j]+f(j+1,i)) (1<=j<=i-1)

右面dp[i,n]=max(dp[i,n],f(i,j)+dp[j+1,n]) (i<=j<=n-1)

f(i,j)表示从i删到j的值

初始化dp[i,n]=f(i,n) , dp[1,i]=f(1,i)

var
dp:array[0..1000,1..2]of longint;
x:array[0..1000]of longint;
i,j,k:longint;
n,ans:longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;

function f(l,r:longint):longint;
begin
if l=r
then exit(x[l])
else exit(abs(x[r]-x[l])*(r-l+1));
end;

begin
readln(n);
for i:=1 to n do
read(x[i]);
for i:=1 to n do
dp[i,1]:=f(1,i);
for i:=1 to n do
dp[i,2]:=f(i,n);
for i:=2 to n do
for j:=1 to i-1 do
dp[i,1]:=max(dp[i,1],dp[j,1]+f(j+1,i));
dp[n,2]:=x
;
for i:=n-1 downto 1 do
for j:=i to n-1 do
dp[i,2]:=max(dp[i,2],dp[j+1,2]+f(i,j));
dp[0,1]:=0; dp[n+1,2]:=0;
for i:=1 to n do
ans:=max(ans,dp[i,1]+dp[i+1,2]);
writeln(ans);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: