第6部分 数学基础(提高篇)-->第1章 快速幂

1615:【例 1】序列的第 k 个数

时间限制: 1000 ms 内存限制: 524288 KB

【题目描述】
BSNY 在学等差数列和等比数列,当已知前三项时,就可以知道是等差数列还是等比数列。
现在给你序列的前三项,这个序列要么是等差序列,要么是等比序列,你能求出第 k 项的值吗。
如果第 k 项的值太大,对 200907 取模。

【输入】
第一行一个整数 T,表示有 T 组测试数据;
对于每组测试数据,输入前三项 a,b,c,然后输入 k。

【输出】
对于每组数据输出第 k 项的值,对 200907 取模。

【输入样例】

2
1 2 3 5
1 2 4 5

【输出样例】

5
16

【提示】样例说明:第一组是等差序列,第二组是等比数列。

数据范围与提示:对于全部数据,1≤T≤100,1≤a≤b≤c≤1e9,1≤k≤1e9 。

  • 参考程序
#include<cstdio>
typedef long long ll;
ll mod=200907;

ll fastpow(ll a, ll b){
    ll ans=1;
    while(b){
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
int main(){
    ll t,a,b,c,k,ans; scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld%lld%lld",&a,&b,&c,&k);
        if(b-a==c-b){
            ll d = b-a;
            ans = (a+(k-1)*d)%mod;
        }else{
            ll q = b/a;
            ans = a*fastpow(q, k-1)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

1616:A 的 B 次方

时间限制: 1000 ms 内存限制: 524288 KB

【题目描述】给出三个整数 a,b,m,求 a^b mod m 的值。
【输入】一行三个整数 a,b,m。
【输出】一个整数,表示 a^b mod m 的值。
【输入样例】2 100 1007
【输出样例】169
【提示】数据范围与提示:对于全部数据,1≤a,b,m≤109 。

  • 参考程序
#include<cstdio>
typedef long long ll;
ll 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 a,b,m; scanf("%d%d%d",&a,&b,&m);
    printf("%lld\n",pow(a,b,m));
    return 0;
}

1617:转圈游戏

时间限制: 1000 ms 内存限制: 524288 KB

【题目描述】
n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏。
按照顺时针方向给 n 个位置编号,从 0 到 n-1。
最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 1 号位置,……,依此类推。

游戏规则如下:
每一轮第 0 号位置上的小伙伴顺时针走到第 m 号位置,
第 1 号位置小伙伴走到第 m+1 号位置,……,依此类推,
第 n-m 号位置上的小伙伴走到第 0 号位置,
第 n-m+1 号位置上的小伙伴走到第 1 号位置,……,
第 n-1 号位置上的小伙伴顺时针走到第 m-1 号位置。
现在,一共进行了 10^k 轮,请问 x 号小伙伴最后走到了第几号位置。

【输入】输入共 1 行,包含 4 个整数 n、m、k、x,每两个整数之间用一个空格隔开。
【输出】输出共 1 行,包含 1 个整数,表示 10k 轮后 x 号小伙伴所在的位置编号。
【输入样例】10 3 4 5
【输出样例】5

【提示】数据范围与提示:
对于 30% 的数据,0<k<7;
对于 80% 的数据,0<k<1e7 ;
对于 100% 的数据,1<n<1e6,0<m<n,1≤x≤n,0<k<1e9。

  • 参考程序
#include<cstdio>
typedef long long ll;
int n,m,k,x;

ll pow(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1) ans=(ans*a)%n;
        b >>= 1;
        a = (a*a)%n;
    }
    return ans;
}
int main(){
    scanf("%d%d%d%d",&n,&m,&k,&x);
    printf("%lld\n",(x+m*pow(10,k))%n);
    return 0;
}

1618:越狱

时间限制: 1000 ms 内存限制: 524288 KB

【题目描述】
原题来自:HNOI 2008

监狱有连续编号为 1 到 n 的 n 个房间,每个房间关押一个犯人。
有 m 种宗教,每个犯人可能信仰其中一种。
如果相邻房间的犯人信仰的宗教相同,就可能发生越狱。
求有多少种状态可能发生越狱。

【输入】输入两个整数 m 和 n。
【输出】可能越狱的状态数,对 100003 取余。
【输入样例】2 3
【输出样例】6

【提示】样例说明
所有可能的 6 种状态为:{0,0,0},{0,0,1},{0,1,1},{1,0,0},{1,1,0},{1,1,1}。
数据范围与提示:对于全部数据,1≤m≤1e8,1≤n≤1e12 。

  • 分析:越狱情况 = 总情况 - 不可越狱情况。
  1. 总情况:m^n。
  2. 不可越狱情况:如果当前犯人选择 1,下一位犯人可选择情况(m-1)种,依此类推,可得不可越狱情况有:m*(m-1)^(n-1)。
  • 参考程序
#include<cstdio>
typedef long long ll;
ll n,m,mod=100003;

ll pow(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1) ans=(ans*a)%mod;
        b >>= 1;
        a = (a*a)%mod;
    }
    return ans;
}
int main(){
    scanf("%lld%lld",&m,&n);
    if(n<2) printf("0\n");
    else printf("%lld\n",((pow(m,n)-m*pow(m-1,n-1)%mod)+mod)%mod);
    return 0;
}
posted @ 2022-05-21 12:11  HelloHeBin  阅读(154)  评论(0编辑  收藏  举报