您的位置:首页 > 其它

指数循环节

2015-09-09 19:22 323 查看
指数循环节

在有些题目中我们需要对指数进行降幂处理才能计算。比如计算



其中




这里由于

很大,所以需要进行降幂。那么实际上有如下降幂公式



有了上述公式,很多题目就可以得到解决。

题目:http://acm.fzu.edu.cn/problem.php?pid=1759

题意:给定





的值,求

的值。其中





代码如下:

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#include <limits.h>
#include <ctime>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-6)
#define inf (1<<28)
#define sqr(x) (x) * (x)
#define mod 1000000007
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
const int MAX = 1000005;
char str[MAX];
int phi(int n)//欧拉函数
{
int i,res=n,m=sqrt(n);
for(i=2; i<=m; i++)
{
if(n%i==0)
{
res=res/i*(i-1);
while(n%i==0)
n=n/i;
}
}
if(n>1)
res=res/n*(n-1);
return res;
}
ll quick_mod(ll a,ll b,ll m)//快速幂
{
ll c=1;
while(b)
{
if(b&1)
c=c*a%m;
a=a*a%m;
b>>=1;
}
return c;
}
ll solve(ll a,char str[],ll c)//指数循环节
{
ll len=strlen(str);
ll ans=0;
ll p=phi(c);
for(int i=0; i<len; i++)
{
ans=ans*10+str[i]-'0';
ans%=p;
}
ans+=p;
return quick_mod(a,ans,c);
}
int main()
{
ll a,c;
while(~scanf("%I64d%s%I64d",&a,str,&c))
printf("%I64d\n",solve(a,str,c));
return 0;
}


题目:http://acm.hdu.edu.cn/showproblem.php?pid=2837

题意:给定一个递归式

,其中



,求

的值。

分析:本题方法比较明确,先已一直递归上去,直到

,然后从上面再一步一步走回来,每一步都可以进行指

数降幂,这里需要判断。

代码如下:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>

using namespace std;
typedef long long LL;

int phi(int n)
{
int rea = n;
for(int i=2; i*i<=n; i++)
{
if(n % i == 0)
{
rea = rea - rea / i;
while(n % i == 0)  n /= i;
}
}
if(n > 1)
rea = rea - rea / n;
return rea;
}

LL quick_mod(LL a,LL b,LL m)
{
LL ans = 1;
a %= m;
while(b)
{
if(b & 1)
{
ans = ans * a % m;
b--;
}
b >>= 1;
a = a * a % m;
}
return ans;
}

LL check(LL a,LL b,LL p)
{
LL ans = 1;
for(int i=1; i<=b; i++)
{
ans *= a;
if(ans >= p)
return ans;
}
return ans;
}

LL dfs(LL n,LL m)
{
LL p = phi(m);
if(n < 10) return n;
LL x = dfs(n / 10, p);
LL y = check(n % 10, x, m);
if(y >= m)
{
LL ans = quick_mod(n % 10, x + p, m);
if(ans == 0)
ans += m;
return ans;
}
else
return y;
}

int main()
{
int T;
cin>>T;
while(T--)
{
LL n,m;
cin>>n>>m;
cout<<dfs(n,m) % m<<endl;
}
return 0;
}


题目:http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=691

题意:给定一个数组

,然后有

,求如下表达式的值



分析:方法基本跟上题一样,就不多说了。注意特殊处理

的情况。

代码如下:

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
typedef long long LL;
const int N = 105;

LL a
,p
;

LL phi(LL n)
{
LL rea = n;
for(int i=2; i*i<=n; i++)
{
if(n % i == 0)
{
rea = rea - rea / i;
while(n % i == 0) n /= i;
}
}
if(n > 1)
rea = rea - rea / n;
return rea;
}

void Init(LL m)
{
p[0] = m;
for(int i=1; i<N; i++)
p[i] = phi(p[i-1]);
}

LL Solve(int dept,bool &f)
{
LL m = p[dept];
if(m == 1)
{
if(a[dept] > 1) f = 1;
else f = 0;
return 0;
}
if(a[dept] >= m)
{
f = 1;
return 0;
}
LL t = 1;
bool flag = 0;
for(int i=1;i<=a[dept];i++)
{
t = t * i;
if(t >= p[dept])
{
flag = 1;
t %= m;
}
}
LL d = Solve(dept+1,f);
if(f) d += phi(m);
LL ans = 1;
f = 0;
for(int i=0;i<d;i++)
{
ans = ans * t;
if(ans >= m)
{
f = 1;
ans %= m;
}
if(flag) f = 1;
}
return ans;
}

int main()
{
int T;
cin>>T;
while(T--)
{
LL n,m;
cin>>n>>m;
for(int i=0; i<n; i++)
cin>>a[i];
if(m == 1)
{
puts("0");
continue;
}
Init(m);
bool f;
cout<<Solve(0,f)<<endl;
}
return 0;
}


题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1674

题意:已知





,给定



,求

的值,并且有条件


成立。

分析:本题方法很巧妙,由于

。本题就要用到这个,设





那么有


可以看出

又是

的一个子问题,这样一直递归下去最终求得结果,因为

,所以一定有解。

代码如下:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>

using namespace std;
typedef long long LL;

LL phi(LL n)
{
LL rea = n;
LL t = (LL)sqrt(1.0*n);
for(int i=2;i<=t;i++)
{
if(n % i == 0)
{
rea = rea - rea / i;
while(n % i == 0) n /= i;
}
}
if(n > 1)
rea = rea - rea / n;
return rea;
}

LL power(LL a,LL b,LL m)
{
LL ans = 1;
a %= m;
while(b)
{
if(b & 1)
{
ans = ans * a % m;
b--;
}
b >>= 1;
a = a * a % m;
}
return ans;
}

LL Solve(LL a,LL m)
{
if(m == 1) return 0;
LL p = phi(m);
return power(a,p,m) * power(a,Solve(a,p),m) % m;
}

int main()
{
LL a,m;
bool f = 1;
while(cin>>a>>m)
{
if(f) f = 0;
else puts("");
LL ans = 1;
for(int i=1;i<=m;i++)
ans *= i;
cout<<Solve(a,ans)%ans<<endl;
}
return 0;
}


题目:http://acm.hdu.edu.cn/showproblem.php?pid=4335

题意:给定3个整数

,其中





,求满足下面两个条件的


的个数。



分析:

,所以这样就容易多了,注意有个特判。

代码如下:

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
typedef unsigned long long ULL;

int phi(int n)
{
int rea = n;
for(int i=2; i*i<=n; i++)
{
if(n % i == 0)
{
rea = rea - rea / i;
while(n % i == 0) n /= i;
}
}
if(n > 1)
rea = rea - rea / n;
return rea;
}

ULL quick_mod(ULL a,ULL b,ULL m)
{
ULL ans = 1;
a %= m;
while(b)
{
if(b & 1)
{
ans = ans * a % m;
b--;
}
b >>= 1;
a = a * a % m;
}
return ans;
}

ULL f[100005];

int main()
{
int T;
scanf("%d", &T);
for(int t=1; t<=T; t++)
{
ULL b, p, m;
scanf("%I64u %I64u %I64u", &b, &p, &m);
if(b == 0 && p == 1 && m == 18446744073709551615ull)
{
printf("Case #%d: 18446744073709551616\n",t);
continue;
}
int ph = phi(p);
ULL ans = 0;
if(b == 0) ans++;
f[0] = 1;
bool flag = 0;
int i;
for(i=1; i<=m; i++)
{
f[i] = f[i-1] * i;
if(f[i] >= ph)
{
f[i] %= ph;
flag = 1;
if(f[i] == 0) break;
}
if(flag)
{
if(quick_mod(i, f[i] + ph, p) == b)
ans++;
}
else
{
if(quick_mod(i, f[i], p) == b)
ans++;
}
}
for(int k=0; i<=m && k<p; i++, k++)
if(quick_mod(i, ph, p) == b)
ans += 1 + (m - i) / p;
printf("Case #%d: %I64u\n", t, ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: