POJ 3358 数论
来源:互联网 发布:985的学生知乎 编辑:程序博客网 时间:2024/05/21 04:17
求二进制小数循环节
这题必须要先吐槽一下出题的人,某些细节没有写清楚,比如整除的情况下是怎样?(或许没有那样的数据....还有p=0的情况是怎样,这些特殊情况很难说清),数据范围也没用说明。结果把本菜坑的一塌糊涂。。。(T..T)
回归正题:求二进制小数的循环节和循环起点。刚开始这题后来没思路,看解题报告发现人家把小数化为分数时,果断关闭窗口。自己去独立完成。。。(话说这也没想到也忒2B了吧。。。。T...T)这样就找到了规律:
以1/10为例:1/10 2/10 4/10 8/10 16/10 32/10 64/10....(小数话二进制每次*2取整,这不就和分子*2,以分母为余数取模一样吗。。。NC无下限)
取模后:1/10 2/10 4/10 8/10 6/10 2/10 4/10 咦,这不就是个循环吗?循环节为4,循环起点为2,正好与题目相符。。如何去找循环节和循环起点?
由于是二进制,所以分子可以表示为2^x,而模数即q
2^x=2^y(mod p),2^x(2^(y-x)-1)=0(mod p),即p|2^x(2^(y-x)-1),首先把p尽量整除2直到不能整除为止,这个步骤的次数就是满足原式最小的x,并得到p'。2^(y-x)=1(mod p')
根据欧拉定理,t=y-x=phi(p')满足此式。但不是最小值,枚举phi(p')约数。
话说这题被坑了N多个WA。。。题目没说清,自己有两处处理的不好,哎。。。伤不起呀。。
#include <iostream>#include <cstdio>#include <cmath>#include <cstdlib>#include <cstring>#include <vector>#define ss(p,q) scanf("%I64d/%I64d",&p,&q)#define N 1000005#define M 30#define ll __int64#define pb push_back#define Max 9223372036854775807ULLusing namespace std;ll a[N];vector<int>b;void prime(){ int i,j; b.clear(); for (i=2;i<N;i++) if (!a[i]) { b.pb(i); for (j=i*2;j<N;j+=i) a[j]=1; }}ll euler(ll n){ ll res=n,i; if (n==1) return 0; for (i=0;i<b.size();i++) if (n%b[i]==0) { res=res/b[i]*(b[i]-1); while (n%b[i]==0) n/=b[i]; if (n==1) break; } if (n!=1) res=res/n*(n-1); return res;}ll gcd(ll p,ll q){ if (p<q) return gcd(q,p); else if (p%q==0) return q; else return gcd(q,p%q);}ll js(int x,ll q){ ll i=0,res=1,curr=2%q; while (x>0) { if (x&1) res=(res*curr)%q; i++; x>>=1; curr=(curr*curr)%q; } return res;}ll deal(ll t,ll q){ int i,i0; ll mmin=Max; for (i=1;i*i<=t;i++) if (t%i==0) { if (js(i,q)==1) return i; i0=t/i; if (js(i0,q)==1&&i0<mmin) mmin=i0; } return mmin;}int main(){ ll p,q,i,t,x,cas=0; prime(); while (ss(p,q)!=EOF) { cas++; x=0; if (p==0) { cout<<"Case #"<<cas<<": "<<1<<','<<1<<endl; continue; } ll y=gcd(p,q); p/=y;q/=y; ll q1=q; while (q1%2==0) { x++; q1/=2; } x++; t=euler(q1); if (t!=0) t=deal(t,q1); cout<<"Case #"<<cas<<": "<<x<<','<<t<<endl; } return 0;}
- POJ 3358 数论
- POJ 1411 数论+优化
- POJ 2429 数论
- POJ 2480 Longge 数论
- POJ 3090简单数论
- POJ 2689 数论
- POJ 2689 数论
- POJ 数论列表
- POJ 1845 数论
- poj 1150 数论
- poj 1019 数论
- poj 2115(数论)
- POJ--1006--Biorhythms【数论】
- POJ 3292 数论
- POJ【数论/组合/博弈论】
- POJ【1909】数论
- poj 1845 Sumdiv 数论
- poj数论(转)
- VS 2010 - error LNK1123: failure during conversion to COFF: file invalid or corrupt
- 常用adb命令
- hdu 2222 AC自动机 。。
- 搜索引擎SEO之我见
- 一个合格的程序员应该读过哪些书
- POJ 3358 数论
- @Override遇到的问题
- 立波锁屏管家:安卓手机锁屏变得简简单单
- Java中获取当前函数名
- html 编码
- HDU 1863 畅通工程
- CSRF攻击
- 按IE后退按钮时让JSP不读缓存
- Eclipse快捷键大全(转载)