G. 小青争的零食

G. 小青争的零食

解题思路:举证快速幂。假设零食为0,蔬菜为1。按照题意:00->01,01->11,01->10,10->01,10->00,11->10,11->11。对于n,前两个好确定只有00,01,10,11,后面的填充便可以由上面的确定。

a n s = [ a ∗ a a ∗ b b ∗ a b ∗ b ] ∗ [ 0 b 0 0 0 0 a b a b 0 0 0 0 a b ] ans = \begin{bmatrix}a*a&a*b&b*a&b*b\end{bmatrix} * \begin{bmatrix}0&b&0&0\\0&0&a&b\\a&b&0&0\\0&0&a&b\end{bmatrix} ans=[aaabbabb]00a0b0b00a0a0b0b

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double lf;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int inf = 0x7f7f7f7f;
const ll INF = 1e16;
const int N = 1e5+10;
const ll mod = 1e9+7;
const double PI = acos(-1.0);
const double eps = 1e-4;

inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
inline string readstring(){string str;char s=getchar();while(s==' '||s=='\n'||s=='\r'){s=getchar();}while(s!=' '&&s!='\n'&&s!='\r'){str+=s;s=getchar();}return str;}
int random(int n){return (int)(rand()*rand())%n;}
void writestring(string s){int n = s.size();for(int i = 0;i < n;i++){printf("%c",s[i]);}}


typedef struct node{
    ll mx[5][5];
}mx;


mx multiply(mx a,mx b){
    mx c;
    for(int i = 1;i <= 4;i++){
        for(int j = 1;j <= 4;j++){
            c.mx[i][j] = 0;
            for(int k = 1;k <= 4;k++){
                c.mx[i][j] = (c.mx[i][j]+(a.mx[i][k]*b.mx[k][j])%mod)%mod;
            }
        }
    }
    return c;
}
mx fast_power(mx a,ll p){
    mx ans;
    for(int i = 1;i <= 4;i++){
        for(int j = 1;j <= 4;j++) ans.mx[i][j] = 0;
        ans.mx[i][i] = 1;
    }
    while(p){
        if(p&1) ans = multiply(a,ans);
        p >>= 1;
        a = multiply(a,a);
    }
    return ans;
}
void solve(ll n,ll a,ll b){
    if(n == 1ll){
        cout<<a+b<<endl;
        return;
    }
    mx c;
    for(int i = 1;i <= 4;i++){
        for(int j = 1;j <= 4;j++){
            c.mx[i][j] = 0;
        }
    }
    c.mx[1][2]=c.mx[2][4]=c.mx[3][2]=c.mx[4][4]=b;
    c.mx[2][3]=c.mx[3][1]=c.mx[4][3]=a;
    c = fast_power(c,n-2ll);
    ll sum = 0;
    for(int j = 1;j <= 4;j++){
        for(int i = 1;i <= 4;i++){
            ll x;
            if(i == 1) x = (a*a)%mod;
            else if(i == 2) x = (a*b)%mod;
            else if(i == 3) x = (a*b)%mod;
            else x = (b*b)%mod;
            x = (x*c.mx[i][j])%mod;
            sum = (sum+x)%mod;
        }
    }
    cout<<sum<<endl;
}
int main(){
    srand((unsigned)time(NULL));
    ll n,a,b;
    while(~scanf("%lld%lld%lld",&n,&a,&b)){
        solve(n,a,b);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42868863/article/details/113826041