poj3696 快速幂的优化+欧拉函数+gcd的优化+互质
2015-03-05 19:28
309 查看
这题满满的黑科技orz
题意:给出L,要求求出最小的全部由8组成的数(eg: 8,88,888,8888,88888,.......),且这个数是L的倍数
sol:全部由8组成的数可以这样表示:((10^x)-1)*(8/9)
那么有m=((10^x)-1)*(8/9)=k*L,answer即满足条件的最小的x
性质1:若ax=by且a和b互质,那么说明a中没有任何b的质因子,b的质因子一定都在x里。所以x是b的倍数。
所以先想方设法在等式中构造两个互质的数以便化简。我们取p=8/gcd(8,L),q=9*L/gcd(8,L)
那么有p*((10^x)-1)=q*k,且p与q互质【8/gcd(8,L)与L/gcd(8,L)一定互质。8又没有3这个质因子,所以9*L/gcd(8,L)还是会互质】
所以由性质1,(10^x)-1是q的倍数。
所以(10^x)-1=0 (mod q)
(10^x)=1 (mod q)
性质2:欧拉定理。对于正整数a,n,若gcd(a,q)=1,则有a^phi(q)=1 (mod q) 【其中phi是欧拉函数】
这个式子是不是和上面很像呢~
所以若gcd(10,q)=1说明有解,否则无解
对于有解的情况,x=phi(q)就是一个解,但不一定是最小解。actually,0---phi(q)中还可能存在解。
性质3:因为后面有mod n,而余数都是有循环节的。(即一个循环周期的长度,设为r)
eg:如果有10^a=1 (mod q),那么10^(a+r)=1 (mod q)
首先x=0是一个解【10^0=1 (mod q)】。而且已经确定phi(q)也是一个解了。所以phi(q)一定是这个循环节r的倍数。
根据性质3,r肯定也是一个解。而且是最小的。
所以只要枚举phi(q)的约数,找出其中最小的满足条件的即可。
-----------------------接下来是满满的黑科技orz----------------------
Q1:本题数据很大,求gcd的过程会TLE肿么办
A1:因为gcd里面有一个数字是固定的,所以可以用一下黑科技
Q2:求快速幂取模(10^x)%q的时候,数据超了long long的范围,会出错
A2:这样:
其实我也没看懂func是个什么鬼。。。。【逃
AC Code:
View Code
Reference:
http://www.cnblogs.com/rainydays/archive/2012/11/05/2754760.html http://blog.csdn.net/yhrun/article/details/6908470
题意:给出L,要求求出最小的全部由8组成的数(eg: 8,88,888,8888,88888,.......),且这个数是L的倍数
sol:全部由8组成的数可以这样表示:((10^x)-1)*(8/9)
那么有m=((10^x)-1)*(8/9)=k*L,answer即满足条件的最小的x
性质1:若ax=by且a和b互质,那么说明a中没有任何b的质因子,b的质因子一定都在x里。所以x是b的倍数。
所以先想方设法在等式中构造两个互质的数以便化简。我们取p=8/gcd(8,L),q=9*L/gcd(8,L)
那么有p*((10^x)-1)=q*k,且p与q互质【8/gcd(8,L)与L/gcd(8,L)一定互质。8又没有3这个质因子,所以9*L/gcd(8,L)还是会互质】
所以由性质1,(10^x)-1是q的倍数。
所以(10^x)-1=0 (mod q)
(10^x)=1 (mod q)
性质2:欧拉定理。对于正整数a,n,若gcd(a,q)=1,则有a^phi(q)=1 (mod q) 【其中phi是欧拉函数】
这个式子是不是和上面很像呢~
所以若gcd(10,q)=1说明有解,否则无解
对于有解的情况,x=phi(q)就是一个解,但不一定是最小解。actually,0---phi(q)中还可能存在解。
性质3:因为后面有mod n,而余数都是有循环节的。(即一个循环周期的长度,设为r)
eg:如果有10^a=1 (mod q),那么10^(a+r)=1 (mod q)
首先x=0是一个解【10^0=1 (mod q)】。而且已经确定phi(q)也是一个解了。所以phi(q)一定是这个循环节r的倍数。
根据性质3,r肯定也是一个解。而且是最小的。
所以只要枚举phi(q)的约数,找出其中最小的满足条件的即可。
-----------------------接下来是满满的黑科技orz----------------------
Q1:本题数据很大,求gcd的过程会TLE肿么办
A1:因为gcd里面有一个数字是固定的,所以可以用一下黑科技
//q=9*N/gcd(8,N); q=9*N; for (int i=0;i<3;i++) if (q%2==0) q=q/2; else break; 要求的是q/gcd(8,N) 而8分解质因数之后是2^3,也就是说带8的gcd里面最多也只可能有3个2。所以直接把这3个2能除掉的都除掉就行了
//if (gcd(10,q)!=1) ans=0; if ((q%2==0)||(q%5==0)) ans=0; 10的质因子只有2和5。如果q是2或5的倍数,就说明q和10不互质。
Q2:求快速幂取模(10^x)%q的时候,数据超了long long的范围,会出错
A2:这样:
LL func(LL a,LL b,LL c) //a*b%c { long long ret = 0; while (b) { if (b & 1) ret = (ret + a) % c; a = 2 * a % c; b >>= 1; } return ret; } LL pow_mod(LL a,LL b,LL MOD) { if (a==1) return 1; LL t=a%MOD,ans=1; while(b) { if (b&1) ans=func(ans,t,MOD); t=func(t,t,MOD); b>>=1; } return ans; }
其实我也没看懂func是个什么鬼。。。。【逃
AC Code:
#include <iostream>
#include <cstdio>
using namespace std;
#define LL long long
#define MAXL 1000
LL TC=0;
LL N,MOD,TM,q,ans;
int phi[MAXL+5];
int gcd(int a,int b) //辗转相除法,返回gcd(a,b)
{
if (b==0) return a;
return gcd(b,a%b);
}
long long euler(long long n)
{
long long ret = n;
for (long long i = 2; i * i <= n; i++)
if (n % i == 0)
{
ret = ret / i * (i - 1);
while (n % i == 0)
n /= i;
}
if (n > 1)
ret = ret / n * (n - 1);
return ret;
}
/*
LL pow_mod(LL a,LL b,LL MOD)
{
if (a==1) return 1;
LL t=a%MOD,ans=1;
while(b)
{
if (b&1)
ans=ans*t%MOD;
t=t*t%MOD;
b>>=1;
}
return ans;
}
*/
LL func(LL a,LL b,LL c) //a*b%c { long long ret = 0; while (b) { if (b & 1) ret = (ret + a) % c; a = 2 * a % c; b >>= 1; } return ret; } LL pow_mod(LL a,LL b,LL MOD) { if (a==1) return 1; LL t=a%MOD,ans=1; while(b) { if (b&1) ans=func(ans,t,MOD); t=func(t,t,MOD); b>>=1; } return ans; }
int main()
{
//calc_phi(MAXL);
while (~scanf("%I64d",&N))
{
TC++;
if (N==0) break;
//q=9*N/gcd(8,N);
q=9*N;
for (int i=0;i<3;i++)
if (q%2==0)
q=q/2;
else break;
TM=euler(q); //tm=phi[q];
ans=TM;
//if (gcd(10,q)!=1)
if ((q%2==0)||(q%5==0))
ans=0;
else
{
for (LL i=1; i*i<=TM; i++)
if (TM%i==0)
{
LL t1=i,t2=TM/i;
LL M1=pow_mod(10,t1,q);
LL M2=pow_mod(10,t2,q);
//cout<<t1<<" "<<M1<<endl<<t2<<" "<<M2<<endl;
if ((M1==1)&&(t1<ans))
ans=t1;
if ((M2==1)&&(t2<ans))
ans=t2;
}
}
printf("Case %d: ",TC);
cout<<ans<<endl;
}
}
/*
LL len,tmp,N;
int TC=0;
bool ok;
int main()
{
while(~scanf("%I64d",&N))
{
TC++;
if (N==0) break;
tmp=8;
len=1;
ok=false;
if (tmp%N==0) ok=true;
while ((!ok)&&(len<=MAXL))
{
tmp=tmp*10+8;
len++;
if (tmp%N==0)
ok=true;
}
if (ok)
printf("Case %d: %I64d\n",TC,len);
else
printf("Case %d: 0\n",TC);
}
return 0;
}
*/
View Code
Reference:
http://www.cnblogs.com/rainydays/archive/2012/11/05/2754760.html http://blog.csdn.net/yhrun/article/details/6908470
相关文章推荐
- hdu6053_TrickGCD_莫比乌斯反演_快速幂优化_前缀和
- 【数论】gcd|扩展gcd|素数筛法|快速幂|欧拉函数(各种模板)
- (hdu step 7.2.2)GCD Again(欧拉函数的简单应用——求[1,n)中与n不互质的元素的个数)
- (hdu step 7.2.2)GCD Again(欧拉函数的简单应用——求[1,n)中与n不互质的元素的个数)
- hdu 2462(数论:欧拉定理+快速幂取模优化+欧拉函数)
- 素数--筛选法打表,快速幂,欧拉函数,gcd
- poj 2478(快速求解欧拉函数优化版。。。)
- GCD 扩展GCD 快速GCD 模线性方程 模线性方程组 单独求欧拉函数 递推求欧拉函数
- web 优化——快速反应的用户界面(三)
- php+Mysql 优化,百万至千万级快速分页
- KMP字符串快速匹配(next数组优化 有限状态自动机)
- Mysql limit 优化,百万至千万级快速分页,--复合索
- 图形图像处理-之-高质量的快速的图像缩放 补充 使用SSE2优化
- HDOJ GCD 2588【欧拉函数】
- 1408: [Noi2002]Robot 欧拉函数+快速幂
- 随机样本选择——快速求解机器学习中的优化问题
- 百万级数据库记录下的Mysql快速分页优化实例
- 《大话数据结构》读书笔记之快速排序源码及其优化
- UVa 11426 GCD - Extreme (II) (欧拉函数应用·O(N*logN))
- 前端性能优化--如何让用户体验快速删除dom节点