[CF 303D]Rotatable Number解题报告
2015-04-14 15:05
267 查看
题目翻译
http://cojs.tk/cogs/problem/problem.php?pid=1939题解
出于可看性,就不用那么严格的数学语言讲了……首先明确一下“循环数”的定义:比如142857,它乘以1,2,3,4,5,6(必须是连续的这些数)能不重不漏地得到142857的所有循环排列。
假设我们拿到了一个(十进制下的)循环数,不妨取142857.令x=0.142857142857……显然它是一个有理数,设为最简分数q/p((p,q)=1)。
因为x是一个无限纯循环小数,所以(10,p)=1.
我们考察这两组数:
第一组:x=0.142857142857……,2x=0.285714285714……,3x=0.428571428571……,4x=0.571428571428……,5x=0.714285714285……,6x=0.857142857142……
第二组:x=0.142857142857……,10x=1.428571428571……,100x=14.285714285714……,1000x=142.857142857142……,10000x=1428.571428571428……,100000x=14285.714285714285……
根据循环数的定义,第一组和第二组数的小数部分必然相同(不考虑排列顺序,下同),反之亦然。
也就是说,命题:“{q/p,2q/p,...,6q/p}和{q/p,10q/p,...,10^5q/p}两组数的小数部分相同”等价于命题:“142857是循环数”。
由于(p,q)=1,上述小数部分只由分子模p的余数决定。
即,{q,2q,...,6q}和{q,10q,...,10^5q}(模p意义下)这两个无序集合是相同的。下面我们将两个模p意义下的无序集合相同称为这两个集合“同构”(没错,就是为了逼格)
在进一步讨论之前,我们先来看p的取值。由于(p,q)=1,故q对模p有乘法逆元q'。将两个集合都乘以q',得到{1,2,...,6}和{1,10,...,10^5}同构。
显然{1,10,...,10^5}中有一个数模p余2.事实上它是100,显然,第二个集合与{10^2,10^3,...,10^7}同构(不信你自己算一下尾数),即,第二个集合与{2*1,2*10,...,2*10^5}同构,故第一个集合与{2*1,2*2,...,6*2}同构,将其中的2,4,6去掉,我们发现,{1,3,5}和{8,10,12}同构。
易证{1,2,...,6}中没有p的倍数(否则x乘这个数得到一个整数,还怎么玩……),所以p>=7.
那么,8在{1,3,5}中对应谁呢?8和它对应数的差值不是0,而且是p的倍数,故差值>=p。所以8最大能对应1,但{1,3,5}中没有比1小的了,故8只能对应1.也就是说,8-1是p的倍数,根据前面讨论的p>=7,一定有p=7.(这里可以看出循环节长度一定是偶数,若为奇数,例如5,我们就得到了{1,3,5}对应{6,8,10},但6最大对应0,矛盾)。
显然上述论证在n≠6的时候仍然成立:p=循环节长度+1.
所以我们就可以用一种充满逼格的写法:{1,2,...,p-1}和{10^0,10^1,...,10^(p-2)}同构。
你有没有一种怪怪的感觉……
没错,10^1,...,10^(p-2)中没有一个模p余1的数(即,1~p-2都不是φ(p)),那么真相只有一个:
p是质数,而且10是p的一个原根!
而反过来,如果p是质数而且10是p的一个原根,那么{1,2,...,p-1}和{10^0,10^1,...,10^(p-2)}同构,而且10^(p-1)=1(mod p),换言之,1/p的小数循环节长度为p-1,而且这个循环节所组成的数一定是循环数。
事实上,前面所做的论证可以推广至其他进制,只需要将10换成进制基数b即可。
我们再来看原题:给出n,x,求最大的b<x,使得在b进制下存在一个n位循环数。
那么原题就等价于:
给出n,x,求最大的b<x,使得b是素数n+1的一个原根。
对一个素数p,如何判断a是否为p的原根呢?其实只需要检查p-1的所有因数d[1],d[2],...,d[k],如果某个1<=i<=k使得a^d[i]=1(mod p)则a不是p的原根,否则a是p的原根。(其原理是:若a在模p下的指数是t,又有a^(p-1)=1(mod p),则必有t|p-1)。
用快速幂实现,复杂度为O(sqrt(p)logp)。
整个算法是这样的:
1.判断n+1是否为素数,不是素数则无解
2.从x-1向下枚举b,用上述算法检测每个b是否是答案
3.若最终没有找到答案则无解。
题目限制是n<=5*10^6,x<=10^9.算法的复杂度最大可能是O(x*sqrt(n)*logn),但实际上只需要枚举很少的b,因为原根其实挺多的……总之这么就能过。
代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long LL; LL quickpow(LL a,LL n,LL m){ LL ans=1; while(n){ if(n&1) ans=(ans*a)%m; a=(a*a)%m; n>>=1; } return ans; } bool is_prime(LL p){ if(p<2) return false; for(LL i=2;i*i<=p;i++){ if(i<p&&p%i==0) return false; } return true; } bool is_root(LL a,LL p){//a是否为p的原根 if(a%p==0) return false; for(LL i=1;i*i<=p-1;i++){ if((p-1)%i==0){ if(i<p-1&&quickpow(a,i,p)==1) return false; if((p-1)/i<p-1&&quickpow(a,(p-1)/i,p)==1) return false; } } return true; } int main(){ freopen("rotatablenumber.in","r",stdin); freopen("rotatablenumber.out","w",stdout); LL N,X; cin>>N>>X; if(!is_prime(N+1)) cout<<-1<<endl; else{ for(LL b=X-1;b>1;b--){ if(is_root(b,N+1)){ cout<<b<<endl; return 0; } } cout<<-1<<endl; } return 0; }
相关文章推荐
- hdu 1394 解题报告 Minimum Inversion Number
- HDU 1394 Minimum Inversion Number解题报告
- [leetcode] 9. Palindrome Number 解题报告
- [LeetCode]Number of Digit One,解题报告
- [leetcode] 179. Largest Number 解题报告
- usaco Name That Number 解题报告
- 【LeetCode】Convert a Number to Hexadecimal 解题报告
- [leetcode] 313. Super Ugly Number 解题报告
- [Leetcode] 171. Excel Sheet Column Number 解题报告
- Letter Combinations of a Phone Number解题报告
- [Leetcode] 452. Minimum Number of Arrows to Burst Balloons 解题报告
- 哈理工oj 1250-Minimum Inversion Number解题报告
- 【LeetCode】Ugly Number II 解题报告
- [Leetcode] 507. Perfect Number 解题报告
- [leetcode] 306. Additive Number 解题报告
- Single Number | LeetCode OJ 解题报告
- 【LeetCode】Number of Boomerangs 解题报告
- LeetCode 136. Single Number 解题报告
- 【LeetCode】268.Missing Number解题报告
- SDUT_Greatest_Number之折半查找解题报告