快速幂_first

信息学奥赛一本通–6.数学基础(提高篇)-1.快速幂

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

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

【输入】
第一行一个整数 T T T,表示有 T T T 组测试数据;

对于每组测试数据,输入前三项 a , b , c a,b,c a,b,c,然后输入 k k k

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

【输入样例】

2
1 2 3 5
1 2 4 5

【输出样例】

5
16
#include <iostream>
#include <vector>
#include <queue>
#include <deque>
#include <forward_list>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <map>
#include <set>
#include <tuple>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#define IOS {std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}
#define x first
#define y second
#define int long long
#define end(x) {cout<<x<<'\n';return ;}
#define endy {cout<<"YES\n";return ;}
#define endn {cout<<"NO\n"; return }
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N =2*1e5+10;

string s;int n,x,y,i,j,k,l,r;float f;
int d;
int a[N],b[N];
struct node{
    int x,i;
};
void solve();
void solve(){
    int m=200907;
    for(i=1;i<=3;i++){cin>>a[i];}
    bool flag=(a[2]-a[1]==a[3]-a[2]);
    if(flag){
        cin>>x;
        d=a[2]-a[1];
        cout<<(a[1]+(x-1)*d)%m<<endl;
    }
    else {
        cin>>x;x-=1;
        int q=a[2]/a[1];
        int ans=1;
        while(x){
            if(x&1)ans=(q%m * ans%m)%m;
            q = (q%m * q%m)%m;
            x>>=1;
        }
        cout<<(a[1]%m*ans%m)%m<<endl;
    }
}

signed main(){
    IOS
    int _=1;
    cin>>_;
    while(_--)solve();
}

1616:A 的 B 次方

【题目描述】
给出三个整数 a , b , m a,b,m a,b,m,求 a b m o d m a^bmodm abmodm
的值。

【输入】
一行三个整数 a , b , m a,b,m a,b,m

【输出】
一个整数,表示 a b m o d m a^bmodm abmodm
的值。

【输入样例】

2 100 1007

【输出样例】

169

#include <iostream>
#include <vector>
#include <queue>
#include <deque>
#include <forward_list>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <map>
#include <set>
#include <tuple>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#define IOS {std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}
#define x first
#define y second
#define int long long
#define end(x) {cout<<x<<'\n';return ;}
#define endy {cout<<"YES\n";return ;}
#define endn {cout<<"NO\n"; return }
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N =2*1e5+10;

string s;int n,x,y,i,j,k,l,r;float f;
int d;
int a[N],b[N];
struct node{
    int x,i;
};
void solve();
void solve(){
    int m;
    cin>>x>>y>>m;
    int ans=1;
    while(y){
        if(y&1)ans = (ans%m * x)%m;
        x = (x%m * (x%m))%m;
        y>>=1;
    }
    cout<<ans;
}

signed main(){
    IOS
    int _=1;
    //cin>>_;
    while(_--)solve();
}

1617:转圈游戏

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

游戏规则如下:每一轮第 0 号位置上的小伙伴顺时针走到第 m m m 号位置,第 1 号位置小伙伴走到第 m + 1 m+1 m+1 号位置,……,依此类推,第 n − m n−m nm 号位置上的小伙伴走到第 0 号位置,第 n − m + 1 n−m+1 nm+1 号位置上的小伙伴走到第 1 号位置,……,第 n − 1 n−1 n1 号位置上的小伙伴顺时针走到第 m − 1 m−1 m1 号位置。

现在,一共进行了 1 0 k 10^k 10k 轮,请问 x x x 号小伙伴最后走到了第几号位置。

【输入】
输入共 1 行,包含 4 个整数 n 、 m 、 k 、 x n、m、k、x nmkx,每两个整数之间用一个空格隔开。

【输出】
输出共 1 行,包含 1 个整数,表示 1 0 k 10^k 10k 轮后 x x x 号小伙伴所在的位置编号。

【输入样例】

10 3 4 5

【输出样例】

5

题解:

第一轮:x号走到 ( m + x ) m o d n (m+x)modn (m+x)modn的位置
x -> (m+x)%n
经过 1 0 k 10^k 10k
x -> (10^k * m + x)%n
所以要求 1 0 k 10^k 10k
x -> (10^k%n * m + x)%n

#include <iostream>
#include <vector>
#include <queue>
#include <deque>
#include <forward_list>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <map>
#include <set>
#include <tuple>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#define IOS {std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}
#define x first
#define y second
#define int long long
#define end(x) {cout<<x<<'\n';return ;}
#define endy {cout<<"YES\n";return ;}
#define endn {cout<<"NO\n"; return }
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N =2*1e5+10;

string s;int n,x,y,i,j,k,l,r;float f;
int d;
int a[N],b[N];
struct node{
    int x,i;
};
void solve();
void solve(){
    int m;
    cin>>n>>m>>k>>x;
    //x -> (m+x)%n
    //x -> (10^k * m + x)%n
    //x -> (10^k%n * m + x)%n
    int ans=1;int q=10;
    while(k){
        if(k&1)ans = (ans%n * q%n)%n;
        q = (q%n * q%n)%n;
        k>>=1;
    }
    cout<<(ans%n * m + x)%n;
}

signed main(){
    IOS
    int _=1;
    //cin>>_;
    while(_--)solve();
}

1618:越狱

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

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

【输入】
输入两个整数 m m m n n n

【输出】
可能越狱的状态数,对 100003 取余。

【输入样例】

2 3

【输出样例】

6

题解:

总共的情况 m n m^n mn
不能越狱的情况 m ∗ ( m − 1 ) x , x = n − 1 m * (m-1)^x,x=n-1 m(m1)x,x=n1
缘由 :考虑 第一间 m m m 第二间和第一间不同 m − 1 m-1 m1,第三间和第二间不同 m − 1 m-1 m1…以此类推
特殊情况 m = 1 m=1 m=1,那么只有一种情况,而且必越狱
坑点: m n m^n mn m ∗ ( m − 1 ) x , x = n − 1 m * (m-1)^x,x=n-1 m(m1)x,x=n1 的相对大小不能确定!需要做最后处理

#include <iostream>
#include <vector>
#include <queue>
#include <deque>
#include <forward_list>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <map>
#include <set>
#include <tuple>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#define IOS {std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}
#define x first
#define y second
#define int long long
#define end(x) {cout<<x<<'\n';return ;}
#define endy {cout<<"YES\n";return ;}
#define endn {cout<<"NO\n"; return }
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N =2*1e5+10;

string s;int n,x,y,i,j,k,l,r;float f;
int d;
int a[N],b[N];
struct node{
    int x,i;
};
void solve();
void solve(){
    int m;
    cin>>m>>n;

    int n_t=n,m_t=m;
    int mm=100003;

    if(m==1)end(1)
    //m m-1 m-1 m-1
    //m m-1 m-1
    int ans=1;
        // (m-1)^(n-1)
        k=(m-1);
        int nk=n-1;
        while(nk){
            if(nk&1)ans = (ans%mm * k%mm)%mm;
            k = (k%mm * k%mm)%mm;
            nk>>=1;
        }
        ans = (ans%mm * m%mm)%mm;
    //m^n

    int all=1;
    m=m_t;n=n_t;
    while(n){
        if(n&1)all = (all%mm * m%mm)%mm;
        m = ( m%mm * m%mm )%mm;
        n>>=1;
    }
    cout<<(all-ans+mm)%mm;//!!!!注意

}

signed main(){
    IOS
    int _=1;
    //cin>>_;
    while(_--)solve();
}
C++ 中,处理大整数(如长整型)的次方运算并取模通常涉及到高效的算法,比如快速幂算法(Fast Exponentiation)。这个算法利用了指数的二进制表示,避免直接对大整数进行多次乘法。 以下是一个使用迭代快速幂算法C++ 代码示例,用于计算长形整数 a 的 b 次幂取模 c: ```cpp #include <vector> #include <string> // 将字符串转换为长整型 long long int strToLong(const std::string &str) { long long int result = 0; for (char c : str) { if (isdigit(c)) result = result * 10 + c - '0'; } return result; } // 快速幂取模 long long int fastPowerMod(long long int base, long long int exponent, long long int modulus) { long long int result = 1; base %= modulus; // 取模操作,防止溢出 while (exponent > 0) { // 如果指数是奇数,则将结果乘以base并取模 if (exponent % 2 == 1) result = (result * base) % modulus; // 将指数除以2并平方base exponent /= 2; base = (base * base) % modulus; } return result; } int main() { std::string num_str1, num_str2, mod_str; std::cout << "Enter the first number: "; std::getline(std::cin, num_str1); std::cout << "Enter the second power: "; std::cin >> num_str2; std::cout << "Enter the modulus: "; std::cin >> mod_str; long long int a = strToLong(num_str1); long long int b = strToLong(num_str2); long long int c = strToLong(mod_str); long long int result = fastPowerMod(a, b, c); std::cout << "Result (modulus): " << result << "\n"; return 0; } ``` 在这个例子中,`strToLong` 函数用于将输入的字符串转换为长整型,然后 `fastPowerMod` 函数实现了快速幂算法,最后在 `main` 函数中调用这些功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值