NOIP2015模拟1

传送门

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<= 263

题解

我们观察一下这个无限序列的产生过程
1,10,101,10110,10110101……
我们可以发现,从第三次开始,第I次得到的序列为第I-1次的序列后接上第I-2次的序列,即斐波那契的构成方法
对于询问[L,R]可以变成f(1,R)-f(1,L-1)
最多91次就可以得到 263 长度的序列了,所以我们与按操作次数处理出该串内的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[n];
 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.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值