[二分][快速幂] 气球消消乐

气球消消乐

问题描述

蒜头君有 n 只气球,蒜头君把气球排成一排。初始时,气球都是白色,现在蒜头君想用 m 种颜色给气球涂色,如果相邻的气球的颜色相同,这 2 个气球会发生消消乐,蒜头君希望你求出会发生消消乐的涂色方法有多少种。最后答案对 10^9+7取模。
输入格式

输入两个整数n(1<=n<=10 ^ 12),m(1<=m<=10^8)
输出格式

输出一行表示答案。
样例输入

3 4
样例输出

28


这是一题简单的组合排序问题。
题目要求发生消消乐的涂色方法有多少种 ?我们可以求出不发生消消乐的情况数x,用总的情况数y减去x即可。
很明显 x = m ∗ ( m − 1 ) n − 1 x = m*(m - 1)^{n-1} x=m(m1)n1 (第一个有m种涂法,第一个往后每一个有m-1种涂法)。
总数 y = m n y=m^n y=mn .
即答案为 m n − m ∗ ( m − 1 ) n − 1 m^n- m*(m - 1)^{n-1} mnm(m1)n1
因为n的范围为10^12所以使用快速幂。

最后注意取模的时候 需要加上一个mod,要不然会出现负数的情况。

ans = (pow_mod(m, n, mod) - (m * pow_mod(m - 1, n - 1,mod)) % mod + mod) % mod

#include<iostream>
typedef long long ll;
using namespace std;
const ll mod = 1e9 + 7;

ll pow_mod(ll a, ll n, ll m) { //求a的n次方并对m取模的结果
    ll ans = 1;
    while(n) {
        if (n&1) {
            ans = (ans * a) % m;
        }
        a = (a * a) % m;
        n >>= 1;
    }
    return ans % mod;
}
int main () {
    int n, m;
    cin >> n >> m;
    ll ans = (pow_mod(m, n, mod) - (m * pow_mod(m - 1, n - 1,mod)) % mod + mod) % mod;
    cout << ans << endl;
    return 0;
    
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值