hdu 2837 Calculation (指数循环节+欧拉函数)

题目链接

题意:

Assume that f(0) = 1 and 0^0=1. f(n) = (n)^f(n/10) for all n bigger than zero. Please calculate f(n)%m. (2 ≤ n , m ≤ 10^9, x^y means the y th power of x).

思路:指数循环节。

trick点在于0^0=1这点。

比较容易想到的一层是ksm的时候特判。

比较不容易想到的一层是,0作为底数的时候,可能出现0^a在用降幂公式加速后,出现0^0。

举个例子:

680 80

phi(80)=32,恰好是8^6的因子

而0^(8^6)答案应该为0,用降幂公式加速后变成了0^0,答案变成了1,结果错误

究其原因,是因为这道题中底数可能有0以及0^0是题目中定义的运算。

解决办法是ksm的结果判断一下,如果是0就加mod。

/* ***********************************************
Author :111qqz
Created Time :Sun 30 Oct 2016 07:19:02 PM CST
File Name :code/hdu/2837.cpp
************************************************ */
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define fst first
#define sec second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ms(a,x) memset(a,x,sizeof(a))
typedef long long LL;
#define pi pair < int ,int >
#define MP make_pair
using namespace std;
const double eps = 1E-8;
const int dx4[4]={1,0,0,-1};
const int dy4[4]={0,-1,1,0};
const int inf = 0x3f3f3f3f;
LL n,m;
LL digit[20];
int cnt;
LL ksm( LL a,LL b,LL mod)
{
   // cout<<"a:"<<a<<" b:"<<b<<" mod:"<<mod<<" ";
    if (b==0) return 1;
    if (a==0) return 0; //任何数的0次方都为1,0的任何除0外次方等于0.
    LL res = 1;
    while (b>0)
    {
	if (b&1) res = ( res * a) % mod;
	b = b >> 1LL;
	a =  ( a*a) % mod;
    }
   // if (res<mod) res = res+mod;
      if (res==0) res = mod;
   // cout<<" res:"<<res<<endl;
    return res;
}
LL euler( LL x)
{
    LL ret = 1;
    for ( LL i =2 ; i * i <= x ; i++)
    {
	if (x%i==0)
	{
	    x/=i;
	    ret*=(i-1);
	    while (x%i==0)
	    {
		x/=i;
		ret*=i;
	    }
	}
    }
    if (x>1) ret*=(x-1);
    return ret;
}
LL fun( LL n,LL m)
{
    if (n<10) return n;
    LL x = fun(n/10,euler(m));
 //   cout<<"n:"<<n<<" m:"<<m<<" x:"<<x<<endl;
    if (x>=euler(m)) x = x%euler(m) + euler(m);
    return ksm(n,x,m); 
}
int main()
{
	#ifndef  ONLINE_JUDGE 
//	freopen("code/in.txt","r",stdin);
  #endif
	int T;
	cin>>T;
	while (T--)
	{
	    scanf("%lld%lld",&n,&m);
	    printf("%lld\n",fun(n,m)%m);
	}
  #ifndef ONLINE_JUDGE  
  fclose(stdin);
  #endif
    return 0;
}