• bzoj3328 PYXFIB


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3328

    【题解】

    真心巧妙。

    这个式子看起来不大好,稍作化简。

    斐波那契数列第n项是斐波那契矩阵的n次方的左上角的数。

    化成矩阵形式。

    考虑二项式定理的矩阵形式。

    就差一个[i mod k = 0]不对了,我们就需要构造一个式子,使得当i mod k = 0的时候该式子为1,否则为0.

    考虑单位根,原根。

    令g为原根,那么单位根w=g^((n-1)/k),且题目保证了k|n-1。

    那么对于i属于[0,k-1],当且仅当i=0的时候,w^i=1。

    那么构造

    这个式子当i mod k=0的时候,w^i=k,否则为0.

    进一步,除以一个k就能完成要求了。

    然后我们将这个代入ans。

    我们设B为答案矩阵,B[1,1]即为ans,那么

    稍加转换

    提前sigma,交换位置

    那么我们构造

    观察形式,那么答案就是

    我们枚举k,然后快速幂计算F即可。

    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10;
    
    # define RG register
    # define ST static
    
    ll n;
    int k, mod;
    int g, w, inv, ans;
    
    struct mat {
        int a, b, c, d;
        friend mat operator * (mat a, mat b) {
            mat c;
            c.a = (1ll * a.a * b.a + 1ll * a.b * b.c) % mod;
            c.b = (1ll * a.a * b.b + 1ll * a.b * b.d) % mod;
            c.c = (1ll * a.c * b.a + 1ll * a.d * b.c) % mod;
            c.d = (1ll * a.c * b.b + 1ll * a.d * b.d) % mod;
            return c;
        }
        friend mat operator ^(mat a, ll b) {
            mat ret = a; --b;
            while(b) {
                if(b&1) ret = ret * a;
                a = a * a; 
                b >>= 1;
            }
            return ret;
        }
    }A;
    
    inline int pwr(int a, ll b) {
        int ret = 1;
        while(b) {
            if(b&1) ret = 1ll * ret * a % mod;
            a = 1ll * a * a % mod;
            b >>= 1;
        }
        return ret;
    }
    
    int y[M], yn; 
    inline int G() {
        yn = 0;
        int t = mod-1;
        for (int i=2; i*i<=t; ++i) {
            if(t%i == 0) {
                y[++yn] = i;
                if(i*i != t) y[++yn] = t/i;
            }
        }
        bool gg = 0;
        int g = 2;
        while(1) {
            gg = 0;
            for (int i=1; i<=yn; ++i)
                if(pwr(g, y[i]) == 1) {
                    gg = 1;
                    break;
                }
            if(!gg) return g; 
            ++g;
        }
    }
    
    inline int F(int x) {
        A.a = x+1, A.b = A.c = 1, A.d = x;
        A = A ^ n;
        x = pwr(x, mod-2);
        x = pwr(x, n);
        return 1ll * x * A.a % mod;
    }
    
    void sol() { 
        cin >> n >> k >> mod;
        
        g = G(); 
        w = pwr(g, (mod-1)/k);
        inv = pwr(w, mod-2);
        ans = 0;
    //    cout << w << endl;
        
        for (int i=0, x=1; i<k; ++i, x = 1ll * x * inv % mod) {
            ans = ans + F(x);
            if(ans >= mod) ans -= mod;
        }
        
        ans = 1ll * ans * pwr(k, mod-2) % mod;
        ans = (ans + mod) % mod; 
        cout << ans << endl;
    }
    
    int main() {
        int T; cin >> T;
        while(T--) sol();
        return 0;
    }
    View Code
  • 相关阅读:
    用的fileupload组件实现的大文件上传
    手机刷机
    Bonferroni correction
    FTP 常用命令
    Oracle 10 参数配置说明
    Solaris 10 ftp,telnet,ssh,sendmail
    solaris10下安装oracle10g
    solaris10中安装oracle内核参数的调整
    matlab从txt/csv文件中读取一行
    SUN服务器Solaris10安装步骤
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3328.html
Copyright © 2020-2023  润新知