官方题解:http://blog.sina.com.cn/duoxiao2015
感觉整理太水的题完全没用,从这次之后就不整理水题了,水题定义:比赛时超过300人AC的题目
HDOJ5344、5347、5349均为600+人做出来的水题,解法见官方题解
HDOJ5351
题意:定义一个fib字符串
fib[1]=b
fib[2]=a
fib[i]=fib[i-1]fib[i-2],i>2
fib[n]的前m个字符构成的字符串s,求s的前后缀相等的串最长的长度,s的前后缀不等于s
思路:m的规模明显超过2^64,所以这题要用到大数,我就直接上java写
观测发现,s可以拆成若干个fib[x]之和,把x记录在a数组里,且有a[i]-a[i-1]>=2恒成立
分情况讨论:
情况1:a数组只有一个数,fib[a[0]]=fib[a[0]-2]fib[a[0]-3]fib[a[0]-2],结果就是fib[a[i]-2]
情况2:a数组不止一个数,且把fib[a[0]]拆分成fib[a[0]-1]fib[a[0]-2],并把相同的fib[x]靠后的那个fib[a[i]]拆分成fib[a[i]-1]fib[a[i]-2]
拆分结束,a数组最末尾的值大于1则说明除fib[a[0]-1]外,后面其余的字符构成的后缀,就是结果的长度
拆分结束,a数组最末尾的值不大于1则说明除fib[a[0]]外,后面其余的字符构成的后缀,就是结果的长度
PS:官方题解的思路会比我的思路好
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
static int T,n;
static BigInteger fib[]=new BigInteger[1010];
static BigInteger m,sum;
static BigInteger mod = new BigInteger("258280327");
static int a[]=new int[1010];
public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
T=cin.nextInt();
fib[1]=BigInteger.ONE;
fib[2]=BigInteger.ONE;
for(int i=3;i<1010;i++){
fib[i]=fib[i-1].add(fib[i-2]);
}
while(T--!=0){
n=cin.nextInt();
m=cin.nextBigInteger();
sum=BigInteger.ZERO;
int p=0;
int k=n;
a[p]=k;
while(!m.equals(sum.add(fib[a[p]]))){
a[p]--;
a[p+1]=a[p]-1;
if(m.compareTo(sum.add(fib[a[p]]))==1){
sum=sum.add(fib[a[p]]);
p++;
}
}
//System.out.println("p"+" "+p);
//System.out.println("a:"+" "+a[0]+" "+a[1]+" "+a[2]+" "+a[3]+" "+a[4]+" ");
if(p>0){
sum=m;
boolean flag=false;
for(int i=0;i<p;i++){
if(i!=p&&a[i]-a[i+1]>2){
flag=true;
break;
}
if(i==p){
if(a[p]>=4)flag=true;
}
}
if(flag)sum=sum.subtract(fib[a[0]-1]);
else sum=sum.subtract(fib[a[0]]);
}
if(p==0){
if(a[p]>3)sum=fib[a[p]-2];
else sum=BigInteger.ZERO;
}
System.out.println(sum.mod(mod));
}
}
}