您的位置:首页 > 编程语言 > Go语言

Codeforces Good Bye 2015

2016-01-01 12:18 726 查看
第二场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<=108L,R<=10^8

所以预处理出所有满足条件的数(不超过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[i,j]:前i个位置,最后切出来的是后j个

dp[0,j]=1dp[0,j]=1

很明显的O(N3)的DPO(N^3)的DP

dp[i,j]=dp[i−j,k] (k<j)or((x[i−j−k+1,i−j]<x[i−j+1,i])and(k=j))dp[i,j]=dp[i-j,k]~~(k

我们发现每次是在dp[i−j,k]dp[i-j,k]相当于一个前缀和的转移,所以我们维护一个sum[i,j]sum[i,j]

sum[i,j]sum[i,j]负责转移(k<j)(k的部分

当k>jk>j时一定不转移

当k=jk=j时我们要判断两个等长的字符串的大小,我们用预处理来解决这个问题

lcp:最长公共前缀lcp:最长公共前缀

我们定义lcp[i,j]为从i开始和从j开始的最长公共前缀长度lcp[i,j]为从i开始和从j开始的最长公共前缀长度

当两部分相等时lcp大于等于他俩的长度当两部分相等时lcp大于等于他俩的长度

否则我们判断lcp+1位置的字符大小即可否则我们判断lcp+1位置的字符大小即可

最后,lcp可以用O(N2)的DP处理出来lcp可以用O(N^2)的DP处理出来

lcp[i,j]=lcp[i+1,j+1] (x[i]=x[j])lcp[i,j]=lcp[i+1,j+1]~~(x[i]=x[j])

lcp[i,j]=0 (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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: