• [做题记录-乱做] BZOJ 3328 PYXFIB


    题意

    [sum_{i = 0}^{n} inom{n}{i}f_i[k | i] ]

    (n leq 10^{18}, k leq 20000, T leq 20)

    (f)是斐波那契数。

    题解

    单位根反演

    [[k|n] = frac{1}{k}sum_{i = 0}^{k - 1}w_k^{ni} ]

    找原根

    • 分解(P - 1)

    • 枚举一个数(a)

    • 对于每一个质因子(i), 判断(a^{(P - 1)/ i})是否为(1)

    • 如果对于每一个质因子上面的测试都不是(1), 那就找到了一个原根(a)

    • 2的原根是(1)

    • 原根的所有幂次在剩余系下的取值给出所有原根。

    题解

    搞个矩阵(A)表示斐波那契的转移矩阵, 考虑化式子。

    [sum_{i = 0}^ninom{n}{i}f_i(frac{1}{k}sum_{j = 0}^{k - 1}w_k^{ij}) \ =frac{1}{k}sum_{j = 0}^{k - 1}sum_{i = 0}^ninom{n}{i}(Aw_{k}^j)^i \ =frac{1}{k}sum_{j = 0}^{k - 1}(Aw_k^j+I)^n ]

    求出原根然后算就完了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace IO {
    	char a; int f;
    	template<typename T> inline void read(T &x) {
    		x = 0; f = 1; a = getchar();
    		for(; ! isdigit(a); a = getchar()) if(a == '-') f = -1;
    		for(; isdigit(a); a = getchar()) x = x * 10 + a - '0';
    		x *= f;
    	}
    	template <typename T> inline void write(T x) {
    		if(x > 9) write(x / 10);
    		putchar(x % 10 + '0');
    	}
    } 
    
    using IO :: read;
    using IO :: write;
    
    int P = 998244353;
    inline int mod(int x) { return x + ((x >> 31) & P); }
    inline void pls(int &x, int y) { x = mod(x + y - P); }
    inline void dec(int &x, int y) { x = mod(x - y); }
    inline int power(int x, int k) {
    	int res = 1;
    //	cerr << k << endl;
    	while(k) {
    		if(k & 1) res = 1ll * res * x % P;
    		x = 1ll * x * x % P; k >>= 1;
    	} return res;
    }
    
    #define lep(i, l, r) for(int i = (l); i <= (r); i ++)
    #define rep(i, l, r) for(int i = (l); i >= (r); i --)
    
    using i64 = long long;
    using i128 = __int128;
    using uint = unsigned int;
    using ui64 = unsigned long long;
    
    struct Mat {
    	int a[2][2];
    	Mat() { a[0][0] = a[0][1] = a[1][0] = a[1][1] = 0; }
    	Mat(int _a, int _b, int _c, int _d) {
    		a[0][0] = _a; a[0][1] = _b; a[1][0] = _c; a[1][1] = _d;
    	}
    	inline Mat operator *(const Mat &t) const {
    		Mat r;
    		lep (i, 0, 1)
    			lep (j, 0, 1) 
    				lep (k, 0, 1)
    					r.a[i][j] = (r.a[i][j] + 1ll * a[i][k] * t.a[k][j]) % P;
    		return r;
    	}
    	inline Mat operator ^(i64 k) {
    		Mat res(1, 0, 0, 1);
    		Mat x = *this;
    		while(k) {
    			if(k & 1) res = res * x;
    			x = x * x; k >>= 1;
    		}
    		return res;
    	}
    } ;
    
    const Mat I = Mat(1, 0, 0, 1);
    
    int k, p;
    i64 n;
    
    int findroot(int p) {
    	if(p == 2) return 1;
    	vector<int> factor;
    	int t = p;
    	p --;
    	for(int i = 2; i * i <= p; i ++)
    		if(p % i == 0) {
    			factor.push_back(i);
    			while(p % i == 0) p /= i;
    		}
    	if(p > 1) factor.push_back(p);
    	//cerr << factor.size() << endl;
    	p = t;
    	lep (a, 2, p - 1) {
    		int fail = 0;
    		lep (j, 0, factor.size() - 1) {
    			int i = factor[j];
    			//cerr << i << endl;
    			//cerr << power(a, (P - 1) / i) << endl;
    	//		cerr << a << ' ' << i << ' ' << power(a, (p - 1) / i) << endl;
    			if(power(a, (P - 1) / i) == 1) { fail = 1; break; }
    		}
    		if(! fail) return a;
    	}
    	return -1;
    }
    
    void solve() {//return ;
    	read(n); read(k); read(p);
    	P = p; //cerr << P << endl; 
    	int g = findroot(p); //cerr << g << endl;
    	
    	int w = power(g, (P - 1) / k);
    	int ans = 0;
    	Mat A(1, 1, 1, 0);
    	int W = 1;
    	lep (j, 0, k - 1) {
    		Mat F = A;
    		lep (x, 0, 1)
    			lep (y, 0, 1)
    				F.a[x][y] = 1ll * F.a[x][y] * W % P;
    		F.a[0][0] ++; F.a[1][1] ++;
    		F = F ^ n;
    		ans = (ans + F.a[0][0]) % P;
    		W = 1ll * W * w % P;
    	}
    	ans = 1ll * ans * power(k, P - 2) % P;
    	write(ans);
    	putchar('
    ');
    }
    
    signed main() {
    	//freopen(".in", "r", stdin);
    	//freopen(".out", "w", stdout);
    //	P = p;
    //	cerr << findroot(5) << endl;
    //	return 0;
    	int Case; read(Case);
    	while(Case --) solve();
    	return 0;
    }
    
  • 相关阅读:
    常用正则表达式大全摘录
    非常好用的CSS样式重置表
    Vue2.0 Props双向绑定报错简易处理办法
    kuangbin带我飞QAQ DLX之一脸懵逼
    乘法逆元+快速幂
    kuangbin带我飞QAQ 线段树
    kuangbin带我飞QAQ 最短路
    uva11401:Triangle Counting 递推 数学
    分块
    今日头条”杯2018年湖北省赛(网络赛)
  • 原文地址:https://www.cnblogs.com/clover4/p/15382631.html
Copyright © 2020-2023  润新知