快速幂_first

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

快速幂

  • 1615:【例 1】序列的第 k 个数
  • 1616:A 的 B 次方
  • 1617:转圈游戏
  • 1618:越狱

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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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++)