zoukankan      html  css  js  c++  java
  • LOJ138 类欧几里得算法【万能欧几里得】

    题目链接

    题目描述:求

    [sum_{x=0}^nlfloorfrac{px+r}{q} floor^{k_1}x^{k_2} mod (10^9+7) ]

    数据范围:数据组数 (T=1000)(n,p,q,rle 10^9)(k_1,k_2ge 0,k_1+k_2le 10)

    真正的类欧几里得,过于令人自闭了。

    所以把刚学的万能欧几里得用一用,设Node结构体为 ((cnt_1,cnt_2,ans_{i,j})),表示 ( ext{U,R}) 的个数,和 (k_1=i,k_2=j) 时的答案。所以若 (C=A+B),则

    [egin{aligned} C.cnt_1&=A.cnt_1+B.cnt_1 \ C.cnt_2&=A.cnt_2+B.cnt_2 \ C.ans_{a,b}&=A.ans_{a,b}+sum_{i=0}^asum_{j=0}^binom{a}{i}inom{b}{j}A.cnt_1^iA.cnt_2^jB.ans_{a-i,b-j} end{aligned} ]

    其中第三个柿子把 ((y+A.cnt_1)^a(x+A.cnt_2)^b) 展开就可以得到。

    再把那个模板原封不动地套一遍,时间复杂度 (O(225logmax{p,q}))

    #include<bits/stdc++.h>
    #define Rint register int
    #define MP make_pair
    #define PB push_back
    #define fi first
    #define se second
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    const int mod = 1000000007;
    template<typename T>
    inline void read(T &x){
    	int ch = getchar(); x = 0; bool f = false;
    	for(;ch < '0' || ch > '9';ch = getchar()) f |= ch == '-';
    	for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
    	if(f) x = -x;
    }
    inline void qmo(int &x){x += (x >> 31) & mod;}
    template<typename T>
    inline bool chmax(T &a, const T &b){if(a < b) return a = b, 1; return 0;}
    template<typename T>
    inline bool chmin(T &a, const T &b){if(a > b) return a = b, 1; return 0;}
    int T, C[11][11];
    LL n, p, q, r, k1, k2;
    struct Node {
    	LL cnt1, cnt2;
    	int ans[11][11];
    	Node(){cnt1 = cnt2 = 0; memset(ans, 0, sizeof ans);}
    	Node operator = (const Node &o){cnt1 = o.cnt1; cnt2 = o.cnt2; memcpy(ans, o.ans, sizeof ans); return *this;}
    	Node operator * (const Node &o) const {
    		Node res;
    		res.cnt1 = cnt1 + o.cnt1;
    		res.cnt2 = cnt2 + o.cnt2;
    		memcpy(res.ans, ans, sizeof res.ans);
    		int x = cnt1 % mod, y = cnt2 % mod;
    		for(Rint al = 0;al <= k1;++ al)
    			for(Rint be = 0;be <= k2;++ be)
    				for(Rint i = 0, t1 = 1;i <= al;++ i, t1 = (LL) t1 * x % mod)
    					for(Rint j = 0, t2 = 1;j <= be;++ j, t2 = (LL) t2 * y % mod)
    						qmo(res.ans[al][be] += (LL) C[al][i] * C[be][j] % mod * o.ans[al - i][be - j] % mod * t1 % mod * t2 % mod - mod);
    		return res;
    	}
    };
    template<typename T>
    T ksm(T a, LL b){
    	T res;
    	for(;b;b >>= 1, a = a * a) if(b & 1) res = res * a;
    	return res;
    }
    Node calc(LL p, LL q, LL r, LL n, const Node &a, const Node &b){
    	LL m = (p * n + r) / q;
    	if(!m) return ksm(b, n);
    	if(p >= q) return calc(p % q, q, r, n, a, ksm(a, p / q) * b);
    	return ksm(b, (q - r - 1) / p) * a * calc(q, p, (q - r - 1) % p, m - 1, b, a) * ksm(b, n - (m * q - r - 1) / p);
    }
    inline void work(){
    	Node res, A, B; read(n); read(p); read(r); read(q); read(k2); read(k1);
    	A.cnt1 = 1; B.cnt2 = 1; for(Rint i = 0;i <= k2;++ i) B.ans[0][i] = 1;
    	res.cnt1 = r / q; for(Rint i = 0, t = 1;i <= k1;++ i, t = (LL) t * res.cnt1 % mod) res.ans[i][0] = t;
    	res = res * calc(p, q, r % q, n, A, B);
    	printf("%d
    ", res.ans[k1][k2]);
    }
    int main(){
    	read(T);
    	for(Rint i = 0;i <= 10;++ i){
    		C[i][0] = 1;
    		for(Rint j = 1;j <= i;++ j) qmo(C[i][j] = C[i - 1][j] + C[i - 1][j - 1] - mod);
    	}
    	while(T --) work();
    }
    
  • 相关阅读:
    2.6、实战案例(三)
    2.5、实战案例(二)
    2.4、实战案例(一)
    2.3、视频采集(二):分辨率、摄像头切换、帧率、滤镜
    2.2、视频采集(一):初步采集
    2.1、列举媒体设备
    1.0、本章导读
    linux 下搭建vsftpd
    解决.net core 3.1跨域问题
    SQLServer for linux安装
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/13129167.html
Copyright © 2011-2022 走看看