指数循环节问题学习&&补题

参考:https://blog.csdn.net/acdreamers/article/details/8236942

今天来学习一个新的东西---指数循环节。在有些题目中我们需要对指数进行降幂处理才能计算。比如计算

       

其中

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

        

有了上述公式,很多题目就可以迎刃而解了。

(注意:必须有B\geqslant \phi (C),如果有小于的部分则要分开考虑,其次n^{^{\phi (p)}}(mod p)的p固定n变化的循环节长度为p)

hdu2837

Calculation

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3428    Accepted Submission(s): 856

Problem Description

Assume that f(0) = 1 and 0^0=1. f(n) = (n%10)^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).

Input

The first line contains a single positive integer T. which is the number of test cases. T lines follows.Each case consists of one line containing two positive integers n and m.

Output

One integer indicating the value of f(n)%m.

Sample Input

2

24 20

25 20

Sample Output

16

5

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
ll Euler(ll n)
{
    ll ret=n;
    for(ll i=2;i*i<=n;i++)
     if(n%i==0)
     {
        ret=ret/i*(i-1);//先进行除法防止溢出(ret=ret*(1-1/p(i)))
        while(n%i==0)
          n/=i;
     }
    if(n>1)
        ret=ret/n*(n-1);
       return ret;
}
ll quick_pow(ll a,ll b, ll m)
{
    ll ans = 1;
    while(b)
    {
        if(b&1)ans = (ans * a)%m;
        b>>=1;
        a = (a*a)%m;
    }
    return ans;
}

ll check(ll a,ll b,ll m)
{
    ll ans = 1;
    while(b)
    {
        ans *=a;
        b--;
        if(ans>=m)return ans;
    }
    return ans;
}

ll f(ll n,ll m)
{
    if(n<10)
        return n;
    ll phi=Euler(m);
    ll x = f(n/10,phi);
    ll y = check(n%10,x,m);
    if(y<m)return y;
    ll ans = quick_pow(n%10,x%phi+phi,m)%m;
    if(!ans)ans += m;
    return ans;
}
int main()
{
    int t;
    ll n,m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        printf("%lld\n",f(n,m));
    }
}

zoj2674

Strange Limit


Time Limit: 5 Seconds      Memory Limit: 32768 KB


Consider sequence an defined with the following recurrence:

a1= p,
an+1= pan 
for n >= 1,

where p is some prime number. Let

bn = an mod m!,

where m! denotes m factorial, that is m! = 1 · 2 · ... · m.

It may seem strange, but for all p and all m the sequence bn has limit as n . Your task is to find it. Given p and m, find

Input

There are several test cases in the input. Each case contains p and m (2 <= p, m <= 12p is prime). There is am empty line between each case.

Output

Output the limit requested. There should be am empty line between each case.

Example

Input Output
2 2 0
2 3 4
3 8 30267
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
ll Euler(ll n)
{
    ll ret=n;
    for(ll i=2;i*i<=n;i++)
     if(n%i==0)
     {
        ret=ret/i*(i-1);//先进行除法防止溢出(ret=ret*(1-1/p(i)))
        while(n%i==0)
          n/=i;
     }
    if(n>1)
        ret=ret/n*(n-1);
       return ret;
}
ll quick_pow(ll a,ll b, ll m)
{
    ll ans = 1;
    while(b)
    {
        if(b&1)ans = (ans * a)%m;
        b>>=1;
        a = (a*a)%m;
    }
    return ans;
}

ll check(ll a,ll b,ll m)
{
    ll ans = 1;
    while(b)
    {
        ans *=a;
        b--;
        if(ans>=m)return ans;
    }
    return ans;
}

ll f(ll n,ll m)
{
    if(m==1)
    {
        return 0;
    }
    ll phi = Euler(m);
    return quick_pow(n,f(n,phi)%phi+phi,m)%m;
}
int main()
{
    int t;
    ll p,m;
    bool flag = true;
    while(~scanf("%lld%lld",&p,&m))
    {
        if(flag)flag=false;
        else puts("");
        ll tmp = 1;
        for(ll i = 1;i<=m;i++)tmp*=i;
        m = tmp;
        printf("%lld\n",f(p,m));
    }
}

hdu4335

What is N?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1794    Accepted Submission(s): 515


 

Problem Description

  (This problem is really old&easy and any acmer who is good at math may solve it in second)
  As we know, math is both intangible and specific. Today you are going to solve the following math problem:
  Given one non-negative integer b, one positive number P and one positive integer M, how many n could you find to satisfy the following 2 rules?


  Here n! means n factorial , 0!=1,1!=1,2!=2,3!=6…,n!=(n-1)!*n

 

Input

  In the first line of the input , we have one integer T indicating the number of test cases. (1 <= T <= 20)
  Then T cases follows.
  For every case, only 3 integers (b, P and M) in a single line. ( 0<=b<P, 1<=P<=10^5, 1 <= M <=2^64 – 1 )

 

Output

  For each test case, first you should print "Case #x: " in a line, where x stands for the case number started with 1. Then one integer indicates the number of "n" that you can find.

Sample Input

3

1 2 3

2 3 4

3 4 5

Sample Output

Case #1: 2

Case #2: 0

Case #3: 0

 

题意:给定满足图片中公式的n的个数。

思路:分成3个部分计算,第一部分n!<phi(p),原公式暴力即可。

第二部分n!>=phi(p)&&n!%p!=0,这一部分将公式转换为后暴力。

第三部分n!>=phi(p)&&n!%p==0,公式变为n^(phi(p))%p==b,左边有循环节,长度为p,只要将循环节内的结果计算出来即可。

有一个坑点需要特殊处理。

#include<iostream>
#include<stdio.h>
#include<map>
#include<string.h>
using namespace std;
typedef unsigned long long ll;
ll Euler(ll n)
{
    ll ret=n;
    for(ll i=2;i*i<=n;i++)
     if(n%i==0)
     {
        ret=ret/i*(i-1);//先进行除法防止溢出(ret=ret*(1-1/p(i)))
        while(n%i==0)
          n/=i;
     }
    if(n>1)
        ret=ret/n*(n-1);
       return ret;
}
ll quick_pow(ll a,ll b, ll m)
{
    ll ans = 1;
    while(b)
    {
        if(b&1)ans = (ans * a)%m;
        b>>=1;
        a = (a*a)%m;
    }
    return ans;
}
int main()
{
    int t   ;
    ll b,p,m;
    scanf("%d",&t);
    for(int tt=1;tt<=t;tt++)
    {
        scanf("%llu%llu%llu",&b,&p,&m);
        if(p==1)
        {
            if(m == 18446744073709551615ULL)
            {
                printf("Case #%d: 18446744073709551616\n",tt);
            }
            else printf("Case #%d: %llu\n",tt,m+1);
            continue;
        }
        ll phi = Euler(p);
        ll x;
        ll len=p;
        ll ans = 0;
        if(b==0)ans++;
        ll nn = 1,n;
        bool flag=false;
        for(n = 1;n<=m;n++)
        {
            nn = nn * n;
            if(nn>=phi)
            {
                nn %= phi;
                flag=true;
                if(nn==0)break;
            }
            if(!flag)
                if(quick_pow(n,nn,p)==b)ans++;
            else
                if(quick_pow(n,nn + phi,p)==b)ans++;
        }
        ll tmp = n;
        for(;n<tmp+p&&n<=m;n++)
        {
            x = quick_pow(n,phi,p);
            if(x == b)
                ans += (m-tmp+1)/p+((m-tmp+1)%p>=(n-tmp+1)?1:0);
        }
        printf("Case #%d: %llu\n",tt,ans);
    }
}

牛客网2018暑假多校训练营第四场A

链接:https://www.nowcoder.com/acm/contest/142/A
来源:牛客网
 

时间限制:C/C++ 4秒,其他语言8秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

A ternary string is a sequence of digits, where each digit is either 0, 1, or 2.
Chiaki has a ternary string s which can self-reproduce. Every second, a digit 0 is inserted after every 1 in the string, and then a digit 1 is inserted after every 2 in the string, and finally the first character will disappear.
For example, ``212'' will become ``11021'' after one second, and become ``01002110'' after another second.
Chiaki would like to know the number of seconds needed until the string become an empty string. As the answer could be very large, she only needs the answer modulo (109 + 7).

输入描述:

There are multiple test cases. The first line of input is an integer T indicates the number of test cases. For each test case:
The first line contains a ternary string s (1 ≤ |s| ≤ 105).
It is guaranteed that the sum of all |s| does not exceed 2 x 106.

输出描述:

For each test case, output an integer denoting the answer. If the string never becomes empty, output -1 instead.

示例1

输入

复制

3
000
012
22

输出

复制

3
93
45

题意:一个只包含012的串,每秒先在1后加0再在2后加1最后消除第一个字符,问多长时间能消除所有的字符。

思路:

(1)如果在消除一个 0 前经过了 n 秒,那么消掉这个 0 需要 n + 1 秒。

(2)如果在消除一个 1 前经过了 n 秒,那么消掉这个 1 与其产生的所有数需要 (n + 1) * 2 秒。

(3)如果在消除一个 2 前经过了 n 秒,那么消掉这个 2 与其产生的所有数需要 (2 ^ (n + 1) - 1) * 3 秒。

需要用欧拉定理降幂。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e5+10;
char s[maxn];
map<ll,ll>phi;
ll quick_pow(ll a,ll b,ll mod)
{
    ll ans = 1;
    while(b)
    {
        if(b&1)ans = (ans * a)%mod;
        b>>=1;
        a = (a * a)%mod;
    }
    return ans;
}
int Euler(int n)
{
    int ret=n;
    for(int i=2;i*i<=n;i++)
    if(n%i==0)
    {
        ret=ret/i*(i-1);//先进行除法防止溢出(ret=ret*(1-1/p(i)))
        while(n%i==0)
        n/=i;
    }
    if(n>1)
        ret=ret/n*(n-1);
    return ret;
}    
void init()
{
    phi.clear();
    phi[1]=1;
    ll x = mod;
    while(x!=1)
    {
        phi[x] = Euler(x);
        x = phi[x];
    }
}
ll dfs(ll x,ll md)
{
    if(x == -1||md == 1)
        return 0;
    if(s[x]=='0')
        return (dfs(x-1,md)+1ll)%md;
    else if(s[x]=='1')
        return ((dfs(x-1,md)+1)*2ll)%md;
    else
    {
        ll tmp = dfs(x-1,phi[md]);
        return (6ll*quick_pow(2ll,tmp,md)-3+md)%md;
    }
}    
int main()
{
    init();
    int i,j,k,l,m,n,T,r,d,cnt,u;
    scanf("%d",&T);
    while(T--)
    {
        ll ans=0;
        scanf("%s",s); 
        l=strlen(s);
        bool flag=false;
        printf("%lld\n",dfs(l-1,1000000007));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_25576697/article/details/81312757