poj 3358 Period of an Infinite Binary Expansion(数论:欧拉函数+快速幂取模)

本文主要是介绍poj 3358 Period of an Infinite Binary Expansion(数论:欧拉函数+快速幂取模),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

不太好理解题意的一道题

给出一个除式

要求找到对应二进制的循环起点和最小循环节长度

这里还考察了分数化小数的知识点。。。

这点不会难怪看题解都觉得很吃力尴尬

1/10

分数化小数的规律如下:

0.1 0.2 0.4 0.8 1.6 1.2 0.4(每次取左侧一位×2,如果大于10,小数位取1,再把这一位%10)

0    0    0   0    1    1    0

以1/10为例:1/10 2/10 4/10 8/10 16/10 32/10 64/10....

取模后:1/10 2/10 4/10 8/10 6/10 2/10 4/10 

这不就是个循环吗?循环节为4,循环起点为2,正好与题目相符。。如何去找循环节和循环起点?

由于是二进制,所以分子可以表示为2^x,而模数即q

2^x=2^y(mod q),2^x(2^(y-x)-1)=0(mod q),即p|2^x(2^(y-x)-1)

因为x^(y-1)-1为奇数,所以p|2^x

首先把q尽量整除2直到不能整除为止,这个步骤的次数就是满足原式最小的x,并得到q'。

2^(y-x)=1(mod q')

根据欧拉定理,t=y-x=phi(q')满足此式。

因为2^phi(q')和q'的最大公约数可能不为1

所以不一定是最小值,需要枚举phi(q')约数。

用int交就WA,用long long就过了

代码如下:

<span style="font-size:18px;">#include <cmath>
#include <vector>
#include <cstdio>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;char str[100];
vector<LL> vec;LL gcd(LL a, LL b) {return b ? gcd(b, a%b) : a;
}LL euler_phi(LL n) {LL ans = n;LL m = sqrt(n+0.5);for(LL i=2; i<=m; ++i) {if(n%i == 0) {n /= i;ans = ans/i*(i-1);while(n%i == 0)n /= i;}}if(n > 1)ans = ans/n*(n-1);return ans;
}void get_fac(LL n) {LL m = sqrt(n+0.5);for(LL i=1; i<=m; ++i) {if(n%i == 0) {vec.push_back(i);if(n/i != i)vec.push_back(n/i);}}
}LL pow_mod(LL a, LL b, LL m) {LL ans = 1;while(b) {if(b & 1) {ans = ans*a%m;}a = a*a%m;b >>= 1;}return ans%m;
}int main(void) {char ch;LL cas = 0, tmp, x, y, p, q;while(scanf("%s", str) != EOF) {vec.clear();sscanf(str, "%lld%c%lld", &p, &ch, &q);if(!p) {printf("Case #%lld: 1,1\n", ++cas);continue;}//printf("p = %d\tq = %d\n", p, q);tmp = gcd(p, q);p /= tmp;q /= tmp;x = 1;while(q % 2 == 0) {q >>= 1;++x;}tmp = euler_phi(q);get_fac(tmp);sort(vec.begin(), vec.end());for(int i=0; i<vec.size(); ++i) {if(pow_mod(2, vec[i], q) == 1) {y = vec[i];break;}}printf("Case #%lld: %lld,%lld\n", ++cas, x, y);}return 0;
}</span>



这篇关于poj 3358 Period of an Infinite Binary Expansion(数论:欧拉函数+快速幂取模)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1059206

相关文章

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

springboot security快速使用示例详解

《springbootsecurity快速使用示例详解》:本文主要介绍springbootsecurity快速使用示例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录创www.chinasem.cn建spring boot项目生成脚手架配置依赖接口示例代码项目结构启用s

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

kotlin的函数forEach示例详解

《kotlin的函数forEach示例详解》在Kotlin中,forEach是一个高阶函数,用于遍历集合中的每个元素并对其执行指定的操作,它的核心特点是简洁、函数式,适用于需要遍历集合且无需返回值的场... 目录一、基本用法1️⃣ 遍历集合2️⃣ 遍历数组3️⃣ 遍历 Map二、与 for 循环的区别三、高

Jackson库进行JSON 序列化时遇到了无限递归(Infinite Recursion)的问题及解决方案

《Jackson库进行JSON序列化时遇到了无限递归(InfiniteRecursion)的问题及解决方案》使用Jackson库进行JSON序列化时遇到了无限递归(InfiniteRecursi... 目录解决方案‌1. 使用 @jsonIgnore 忽略一个方向的引用2. 使用 @JsonManagedR

C++快速排序超详细讲解

《C++快速排序超详细讲解》快速排序是一种高效的排序算法,通过分治法将数组划分为两部分,递归排序,直到整个数组有序,通过代码解析和示例,详细解释了快速排序的工作原理和实现过程,需要的朋友可以参考下... 目录一、快速排序原理二、快速排序标准代码三、代码解析四、使用while循环的快速排序1.代码代码1.由快

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st