Codeforces Good Bye 2015

第二场CF,3题收场

T1 New Year and Days

传送门

http://codeforces.com/contest/611/problem/A

题目大意

询问2016有多少星期几和几号

题解

打表?

var
 n:longint;
 a:string;
begin
 readln(n,a);
 if a=' of week'
 then begin
  case n of
  1:writeln(52);
  2:writeln(52);
  3:writeln(52);
  4:writeln(52);
  5:writeln(53);
  6:writeln(53);
  7:writeln(52);
  end;
 end
 else begin
  if n<=29
  then writeln(12)
  else
   if n=30
   then writeln(11)
   else writeln(7);
 end;
end.

T2 New Year and Old Property

传送门

http://codeforces.com/contest/611/problem/B

题目大意

询问[L,R]中转为二进制后只有一个0的数的个数

题解

L,R<=108
所以预处理出所有满足条件的数(不超过2000个)
询问是扫一遍即可

var
 x:array[0..2000]of int64;
 y:array[0..100]of int64;
 sum,i,j,k,ans:longint;
 l,r,t:int64;
 a,b:int64;
begin
 sum:=0; readln(a,b);
 y[0]:=1;
 for i:=1 to 62 do
  y[i]:=y[i-1]*2;
 for i:=1 to 61 do
  for j:=1 to i-1 do
   begin
    inc(sum);
    x[sum]:=y[i]-1-y[j-1];
   end;
 ans:=0;
 for i:=1 to sum do
  if (x[i]>=a)and(x[i]<=b)
  then inc(ans);
 writeln(ans);
end.

T3 New New Year and Domino

传送门

http://codeforces.com/contest/611/problem/C

题目大意

给定棋盘,若干询问,矩形区域内能放1x2的骨牌方案数

题解

其实不是覆盖问题,就是只放一个有多少位置,要么横着放,要么竖着放,再搞个前缀和就行

var
 w,sum1,sum11,sum2,sum22,sum:array[0..505,0..505]of longint;
 i,j,k,l:longint;
 n,m,t,a,b,c,d,ans:longint;
 cha:char;
begin
 readln(n,m);
 for i:=1 to n do
  begin
   for j:=1 to m do
    begin read(cha); if cha='.' then w[i,j]:=0 else w[i,j]:=1; end;
   readln;
  end;
 for i:=1 to n do
  for j:=1 to m do
   begin
    sum[i,j]:=sum[i-1,j]+sum[i,j-1]-sum[i-1,j-1];
    if (w[i,j]=0)and(w[i-1,j]=0)and(i>=2) then inc(sum[i,j]);
    if (w[i,j]=0)and(w[i,j-1]=0)and(j>=2) then inc(sum[i,j]);
   end;
 for i:=1 to n do
  for j:=2 to m do
   if (w[i,j]=1)or(w[i,j-1]=1)
   then sum2[i,j]:=sum2[i,j-1]
   else sum2[i,j]:=sum2[i,j-1]+1;
 for j:=1 to m do
  for i:=2 to n do
   if (w[i,j]=1)or(w[i-1,j]=1)
   then sum1[i,j]:=sum1[i-1,j]
   else sum1[i,j]:=sum1[i-1,j]+1;
 readln(t);
 for l:=1 to t do
  begin
   readln(a,b,c,d);
   ans:=0;
   for i:=a to c do
    if (w[i,b]=1)or((w[i,b-1]=1)or(b=1))
    then inc(ans,sum2[i,d]-sum2[i,b-1])
    else inc(ans,sum2[i,d]-sum2[i,b-1]-1);
   for i:=b to d do
    if (w[a,i]=1)or((w[a-1,i]=1)or(a=1))
    then inc(ans,sum1[c,i]-sum1[a-1,i])
    else inc(ans,sum1[c,i]-sum1[a-1,i]-1);
   writeln(ans);
  end;
end.

T4 New Year and Ancient Prophecy

传送门

http://codeforces.com/contest/611/problem/D

题目大意

给定一个序列,然后把序列切开,使切出来的数严格递增

题解

DP
dp[i,j]:i,j
dp[0,j]=1
很明显的 O(N3)DP
dp[i,j]=dp[ij,k]  (k<j)or((x[ijk+1,ij]<x[ij+1,i])and(k=j))
我们发现每次是在 dp[ij,k] 相当于一个前缀和的转移,所以我们维护一个 sum[i,j]
sum[i,j] 负责转移 (k<j) 的部分
k>j 时一定不转移
k=j 时我们要判断两个等长的字符串的大小,我们用预处理来解决这个问题
lcp:
我们定义 lcp[i,j]ij
lcp
lcp+1
最后, lcpO(N2)DP
lcp[i,j]=lcp[i+1,j+1]  (x[i]=x[j])
lcp[i,j]=0  (x[i]<>x[j])
当然也可以后缀数组求出,,,

var
 lcp,sum,dp:array[0..5005,0..5005]of longint;
 i,j,k:longint;
 n,ans,tt:longint;
 x,a,b:ansistring;
begin
 readln(n);
 readln(x);
 for i:=n downto 1 do
  for j:=i downto 1 do
   if x[i]=x[j]
   then lcp[i,j]:=lcp[i+1,j+1]+1
   else lcp[i,j]:=0;
 for i:=1 to n do
  for j:=1 to n do
   begin
    if i-j<0 then begin sum[i,j]:=sum[i,j-1]; continue; end;
    if i-j=0
    then begin dp[i,j]:=1; sum[i,j]:=(sum[i,j-1]+dp[i,j])mod 1000000007; continue; end
    else
     if x[i-j+1]='0'
     then begin dp[i,j]:=0; sum[i,j]:=(sum[i,j-1]+dp[i,j])mod 1000000007; continue; end;
    if i-2*j>=0
    then begin
     tt:=lcp[i-j+1,i-2*j+1];
     if (tt>=j)or(x[i-2*j+tt+1]>x[i-j+tt+1])
     then dp[i,j]:=(dp[i,j]+sum[i-j,j-1])mod 1000000007
     else dp[i,j]:=(dp[i,j]+sum[i-j,j-1]+dp[i-j,j])mod 1000000007;
    end
    else dp[i,j]:=(dp[i,j]+sum[i-j,i-j])mod 1000000007;
    sum[i,j]:=(sum[i,j-1]+dp[i,j])mod 1000000007;
   end;
 ans:=0;
 for i:=1 to n do
  ans:=(ans+dp[n,i])mod 1000000007;
 writeln(ans);
end.

你可能感兴趣的:(Codeforces Good Bye 2015)