2012 winter training @HIT Day 3 解题报告
冬训第三天。我发现参加寒假集训contest的同学是一天比一天少。
今天练习java,四道题其实只有Problem B值得一说,而且我还是在『亮亮』学长的思路指点下才写出来的代码。效果倒是真的很不错。
http://acm.hit.edu.cn/hoj/contest/view?id=100129
Problem A:Hello Java
给出A、B、P求 A * B % P,唯一一点就是三者全都0< <=2^63-1。目测C++的longlong会溢出,经我的实地检验果然溢出
(╮(╯_╰)╭|||使用“分配律”((A % P) * (B % P)) % P 也是不行哒)。用java的biginteger一击制敌。
/*This Code is Submitted by acehypocrisy for Problem 4000090 at 2012-01-20 09:21:44*/ import java.util.*; import java.math.*; public class Main { public static void main(String args[]){ Scanner cin = new Scanner(System.in); while (cin.hasNextBigInteger()){ BigInteger A = cin.nextBigInteger(); BigInteger B = cin.nextBigInteger(); BigInteger P = cin.nextBigInteger(); System.out.println(A.multiply(B).mod(P)); } } }
Problem B:Ugly Numbers
寻找丑数,这道题比原题简单,只要输出第1500个即可,所以可以选择本地跑出结果后print上去。在1s之内出结果也是没问题的。下面的代码的思路是亮神指点的,我等蒟蒻受益匪浅……
首先要明确一点的是,因为丑数的因数只有2 3 5三个数,所以说所有丑数(除1外)都是是可以根据之前的丑数推出来的。
存三个数组索引,把他想成三组一样的数据也不为过。一组数据只负责*2,一组只负责*3,一组只负责*5。这样从1开始就可以推出所有的丑数了。首先要保证当前这三个索引所存的数据分别*2、*3、*5之后比目前最大的丑数还要大。然后比较他们*2、*3、*5之后的数据,选择小的那个作为新的丑数,并且对索引进行一些处理以满足上面说的那一条“保证”。然后就是循环了,循环到1500即可。
本地测试0.016s给出结果,oj评测0.00s。
#include <stdio.h> #include <algorithm> using namespace std; struct Index{ int temp; int index; int step; }myindex[3]; bool compare(const Index& A, const Index& B){ if (A.temp < B.temp) return true; else return false; } int ugly_number[1500]; int main() { myindex[0].index = myindex[1].index = myindex[2].index = 0; myindex[0].step = 2; myindex[1].step = 3; myindex[2].step = 5; int n = 1; ugly_number[0] = 1; while (n < 1500){ myindex[0].temp = ugly_number[myindex[0].index] * myindex[0].step; myindex[1].temp = ugly_number[myindex[1].index] * myindex[1].step; myindex[2].temp = ugly_number[myindex[2].index] * myindex[2].step; sort(&myindex[0], &myindex[3], compare); for(int i = 0; i < 3; i++){ if (myindex[i].temp > ugly_number[n-1]){ myindex[i].index++; ugly_number[n] = myindex[i].temp; n++; break; } } for(int i = 0; i < 3; i++){ while (ugly_number[myindex[i].index] * myindex[i].step <= ugly_number[n-1]) myindex[i].index++; } } printf("The 1500'th ugly number is %d.\n", ugly_number[1499]); return 0; }
另外要提到的是我原来的代码myindex是叫index的,但是交上去编译错误,大意就是和string.h里面的一个函数重名了。。。
哦,在多说一句,代码里面中间的for当时是为了挑出最小的、而且比目前最大丑数大的那个数,不过既然有了下面的while,这句for就显得有点多余了。。
Problem C & D:Fibonacci Sequence
最最基本的斐波那契数列了,其实C和D是一样的,只不过D要求高精度了而已。。所以只贴D的代码了,用java
/*This Code is Submitted by acehypocrisy for Problem 4000094 at 2012-01-20 09:35:58*/ import java.util.*; import java.math.*; public class Main { public static void main(String args[]){ Scanner cin = new Scanner(System.in); while (cin.hasNextInt()){ int n = cin.nextInt(); BigInteger F1 = BigInteger.valueOf(0); BigInteger F2 = BigInteger.valueOf(1); BigInteger F3 = F1.add(F2); for (int i = 0;i < n - 2; i++){ F1 = F2; F2 = F3; F3 = F1.add(F2); } if (n == 0) System.out.println(0); else if (n == 1) System.out.println(1); else System.out.println(F3); } } }