挑战程序竞赛系列(38):4.1模运算的世界(1)
来源:互联网 发布:淘宝拆车喇叭 编辑:程序博客网 时间:2024/06/15 01:03
挑战程序竞赛系列(38):4.1模运算的世界(1)
详细代码可以fork下Github上leetcode项目,不定期更新。
练习题如下:
- POJ 1150: The Last Non-zero Digit
POJ 1150: The Last Non-zero Digit
总算刷到了登峰造极,看了一些关于模运算的相关知识,但还是云里雾里,索性就直接开题,该系列每题都开篇博文讲解吧,知识点比较多。
此题推荐博文:http://www.hankcs.com/program/algorithm/poj-1150-the-last-non-zero-digit.html
更详细的解法:http://duanple.blog.163.com/blog/static/7097176720081016113033592/
数论入门推荐书籍:《初等数论及其应用》.
思路:
进行质因数分解,分解2和5,因为只有2和5的乘积才能构成10。在一个序列中:
1 2 3 4 5 6 7 8 9 10因数2的个数永远大于因数5的个数
所以说,我们只需要求出多出来的2的个数即可,这些将会影响非零位数的最终结果。
2的质因数个数如何求解:
1 2 3 4 5 6 7 8 9 10可以分解为:1 3 5 7 9 | 2 4 6 8 10前半部分个数:0后半部分个数:5 + f{1,2,3,4,5}没错,除了个2之后,能够得到5个质因数该问题就变成了子问题{1,2,3,4,5}的质因数个数递归解决,复杂度O(logn)
代码如下:
public int total2(int n){ if (n == 0) return 0; return n / 2 + total2(n / 2); }
质因数5的个数如何?和2一个道理,所以有:
public int total5(int n){ if (n == 0) return 0; return n / 5 + total5(n / 5); }
所以综合下(递归版本):
public int fact_prime(int n, int x){ if (n == 0) return 0; return n / x + fact_prime(n / x, x); }
迭代版本:
public int fact_prime_iter(int n, int x){ int res = 0; while (n > 0){ res += n / x; n = n / x; } return res; }
接着,把所有的2和5的质因数全部排除后,剩余了什么?
1 2 3 4 5 6 7 8 9 101 1 3 1 1 3 7 1 9 1只剩下{1,3,7,9}了,那么为了能够计算非零位数,统计这些1,3,7,9的个数就完事了。统计蛮取巧,分成奇数列和偶数列1 3 5 7 9 | 2 4 6 8 10前半部分的个数分别为:1:2 3:1 7:1 9:1后半部分的个数分别为:子问题{1,2,3,4,5}子问题可以不去考虑了,前半部分怎么统计呢?观察发现它包含有5的奇数倍项,但这奇数倍均除以5得到1,3,5,7....所以变成了前部部分的子问题了...所以问题的关键就变成了求解1,3,7,9各自的个数了其实都不需要求,直接看出来了当n = 10,1:1, 3:1, 7:1, 9:1当n = 13?1:2 3:2 7:1 9:1因为13中有11和13个位数分别为1和3所以给定n我们有 g(n, x) = n / 10 + (n % 10 >= x) + g(n / 5, x);n/10: 每10个数都有一个n%19: n的个位数可能产生一个
好了,代码就出来了:
public int odd_end_with(int n, int x){ if (n == 0) return 0; int res = n / 10; res += (n % 10 >= x ? 1 : 0); return res + odd_end_with(n / 5, x); } public int end_with(int n, int x){ if (n == 0) return 0; return end_with(n / 2, x) + odd_end_with(n, x); }
最后如何计算
很简单,因为N-M完全包含N,所以直接把统计结果减掉即可,最终代码如下:
import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.util.StringTokenizer;public class Main{ String INPUT = "./data/judge/201708/P1150.txt"; public static void main(String[] args) throws IOException { new Main().run(); } int[][] table = { {6, 2, 4, 8}, {1, 3, 9, 7}, // 3 {1, 7, 9, 3}, // 7 {1, 9, 1, 9}, // 9 }; void solve() { while (more()){ int N = ni(); int M = ni(); // 分解质因数 2 和 5 并且分别统计 2 和 5 的个数 int two = fact_prime(N, 2) - fact_prime_iter(N - M, 2); int five = fact_prime(N, 5) - fact_prime_iter(N - M, 5); int remain = two - five; // 统计 1 3 7 9 的个数 int three = end_with(N, 3) - end_with(N - M, 3); int seven = end_with(N, 7) - end_with(N - M, 7); int nine = end_with(N, 9) - end_with(N - M, 9); int ans = 1; ans *= remain == 0 ? 1 : table[0][remain % 4]; ans *= three == 0 ? 1 : table[1][three % 4]; ans *= seven == 0 ? 1 : table[2][seven % 4]; ans *= nine == 0 ? 1 : table[3][nine % 4]; ans %= 10; out.println(ans); } } public int fact_prime(int n, int x){ if (n == 0) return 0; return n / x + fact_prime(n / x, x); } public int fact_prime_iter(int n, int x){ int res = 0; while (n > 0){ res += n / x; n = n / x; } return res; } public int odd_end_with(int n, int x){ if (n == 0) return 0; int res = n / 10; res += (n % 10 >= x ? 1 : 0); return res + odd_end_with(n / 5, x); } public int end_with(int n, int x){ if (n == 0) return 0; return end_with(n / 2, x) + odd_end_with(n, x); } FastScanner in; PrintWriter out; void run() throws IOException { boolean oj; try { oj = ! System.getProperty("user.dir").equals("F:\\java_workspace\\leetcode"); } catch (Exception e) { oj = System.getProperty("ONLINE_JUDGE") != null; } InputStream is = oj ? System.in : new FileInputStream(new File(INPUT)); in = new FastScanner(is); out = new PrintWriter(System.out); long s = System.currentTimeMillis(); solve(); out.flush(); if (!oj){ System.out.println("[" + (System.currentTimeMillis() - s) + "ms]"); } } public boolean more(){ return in.hasNext(); } public int ni(){ return in.nextInt(); } public long nl(){ return in.nextLong(); } public double nd(){ return in.nextDouble(); } public String ns(){ return in.nextString(); } public char nc(){ return in.nextChar(); } class FastScanner { BufferedReader br; StringTokenizer st; boolean hasNext; public FastScanner(InputStream is) throws IOException { br = new BufferedReader(new InputStreamReader(is)); hasNext = true; } public String nextToken() { while (st == null || !st.hasMoreTokens()) { try { st = new StringTokenizer(br.readLine()); } catch (Exception e) { hasNext = false; return "##"; } } return st.nextToken(); } String next = null; public boolean hasNext(){ next = nextToken(); return hasNext; } public int nextInt() { if (next == null){ hasNext(); } String more = next; next = null; return Integer.parseInt(more); } public long nextLong() { if (next == null){ hasNext(); } String more = next; next = null; return Long.parseLong(more); } public double nextDouble() { if (next == null){ hasNext(); } String more = next; next = null; return Double.parseDouble(more); } public String nextString(){ if (next == null){ hasNext(); } String more = next; next = null; return more; } public char nextChar(){ if (next == null){ hasNext(); } String more = next; next = null; return more.charAt(0); } }}
阅读全文
0 0
- 挑战程序竞赛系列(38):4.1模运算的世界(1)
- 挑战程序竞赛系列(39):4.1模运算的世界(2)
- 挑战程序竞赛系列(40):4.1模运算的世界(3)
- 挑战程序竞赛系列(42):4.1模运算的世界(4)
- 挑战程序竞赛系列(15):2.6快速幂运算
- 挑战程序竞赛系列(30):3.4矩阵的幂
- 挑战程序竞赛系列(41):4.1中国剩余定理
- 挑战程序竞赛系列(43):4.1矩阵 高斯消元
- 挑战程序竞赛系列(81):4.3 LCA(1)
- 挑战程序竞赛系列(1):2.3动态规划
- 挑战程序竞赛系列(58):4.6树上的分治法(1)
- 挑战程序竞赛系列(61):4.6平面上的分治法(1)
- 挑战程序竞赛系列(63):4.7字符串上的动态规划(1)
- 挑战程序竞赛系列(47):4.1 计数 二项式取模
- 挑战程序竞赛系列(45):4.1Polya 计数定理(1)
- 挑战程序竞赛系列(82):4.3 LCA(2)
- 挑战程序竞赛系列(4):2.1深度优先搜索
- 挑战程序竞赛系列(5):2.1广度优先搜索
- Centos 多版本python管理
- Maven的应用场景
- Python WorkerThread设计实现
- 调用相机拍照并展示
- ConflictingBeanDefinitionException: Annotation-specified bean name 'errorPageFilter'
- 挑战程序竞赛系列(38):4.1模运算的世界(1)
- PAT乙级——1002写出这个数
- localStorage实现简单web 留言本
- Python While 循环语句
- 欢迎使用CSDN-markdown编辑器
- countAndSay
- 视频实时OpenGL渲染并保存渲染结果合成MP4
- Java学习笔记-方法的重载
- PHP Fatal error: Uncaught Error: Call to undefined function xml_parser_create() 引发的问题