BestCoder 百度之星2016
20160523 百度之星初赛第一场
1001 All X
思路 :对于m个x组成的数,这个数太大无法直接计算。所以应该从另外的角度考虑问题。
首先我们得明确对于乘法和加法的求模运算,可以先乘(加)后模或者先模后乘(加),所得结果是一样的。比如(a*b)%c == ((a%c) * (b%c))%c; (a+b)%c =(a%c+b%c)%c.
所以这一题我们可以转化到求m个1组成的数对k的余数,同样的这个数也很大,但是k的范围不大,我们知道余数的个数最多是k个不同的值,所以余数是有周期的或者说从某一个数开始会循环。我们需要找到周期开始和周期结束的位置。假设 a个1对k的余数是 ak,1的个数不断增加,直到b个1对k的余数 bk == ak;就会得出周期开始是a个1,周期结束是b-1个1.此后,无论1的个数增加到多少,都是在a~b-1这个区间内,区间长度为 b-a。
当有m个数时,m < b时,余数即第m个;m>b时,余数在(m-b)%(b-a)+a 这个位置。
import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNext()) { int t = in.nextInt(); for (int i = 1; i <= t; i++) { int x = in.nextInt(); long m = in.nextLong(); int k = in.nextInt(); int c = in.nextInt(); Map<Integer,Integer> map = new HashMap<Integer,Integer>(); int[] ref = new int[k + 1]; int allOne = 1; int index = 1; //计算1~index个1对k的余数,余数个数最多为k个,所以肯定从某个位置开始有周期,找出周期 //某个余数第二次出现了,这就是周期开始位置 while (!map.containsKey(allOne)) { map.put(allOne, index); ref[index++] = allOne; allOne = (allOne * 10 + 1) % k; } int start = map.get(allOne);//周期开始的位置,map的最后一项是周期结束的位置 int period = index - start;//周期长度 System.out.println("Case #" + i + ":"); int res = 0; if (m < index) { res = (ref[(int) m] * x) % k; //转化成m个x的余数 } else { res = (ref[(int)((m - index) % period + start)] * x) % k; } System.out.println(res == c ? "Yes" : "No"); } } } }
20160514 百度之星资格赛
Problem A
Problem D
Problem B
思路:找规律发现就是求斐波那契数列的值。陷阱在于如果使用long类型来保存结果会越界,所以要用BigInteger,还要注意保存之前的结果,就像测试赛的第一题。
import java.math.BigInteger; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int max = 1; System.out.println(Long.MAX_VALUE); BigInteger[] bi = new BigInteger[201]; bi[0] = new BigInteger("1"); bi[1] = new BigInteger("1"); while (sc.hasNext()) { int n = sc.nextInt(); while (n > max) { bi[max+1] = bi[max].add(bi[max-1]); max++; } System.out.println(bi[n]); } } }
2016 0510 百度之星测试赛
1004 放盘子
思路:不得不说最后的Hint至关重要,差点就蒙了。想通了之后非常简单,就是判断所给圆半径是否不大于正多边形的内切圆半径,不大于的话就会赢,反之则会输。
因为不大于的时候,先手总是可以把盘子放在中心,然后在对称位置放置盘子就好了。反之,则一个盘子也放不进去,所以就会输。
import java.util.Scanner; public class Main { public static void main(String []args){ Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int t = sc.nextInt(); for (int i = 1; i <= t; i++) { int n = sc.nextInt(); double a = sc.nextDouble(); double r = sc.nextDouble(); double ra = a/2 * 1/Math.tan(Math.PI/n); System.out.println("Case #"+i+":"); if(ra >= r) System.out.println("Give me a kiss!"); else System.out.println("I want to kiss you!"); } } } }