官方题解: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)); } } }