ZOJ 3774 二次剩余
题意:简单粗暴,求菲波那契数列每个数的m次的前n项和模1e9+7
思路:斐波那契通项式, 注意到有很多根号5,求二次剩余为5模1e9+7的解,显然我们可以直接找一个(383008016),然后拿来替代根号5,然后优化下,把中括号中共轭的两部分预处理下,然后由于是外部的一个指数m,从1枚举到m,来求二项式定理的每项系数,再用个逆元就好了。人家的校赛题(
/** @Date : 2017-03-18-15.39 * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : */ #include<bits/stdc++.h> #define LL long long #define PII pair<int ,int> #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 1e5+20; const double eps = 1e-8; const LL mod = 1e9 + 9; const LL trem = 383008016; LL fac[N], le[N], ri[N]; LL fpow(LL a, LL n) { LL res = 1; while(n > 0) { if(n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; } LL Inv(LL x) { return fpow(x, mod - 2); } void init() { LL tinv = Inv(2); fac[0] = 1; le[0] = ri[0] = 1; LL l = ((1 + trem + mod)%mod) * tinv % mod; LL r = ((1 - trem + mod)%mod) * tinv % mod; for(LL i = 1; i < N; i++) fac[i] = fac[i - 1] * i % mod; for(int i = 1; i < N; i++) { le[i] = le[i - 1] * l % mod; ri[i] = ri[i - 1] * r % mod; //cout << le[i] <<" " << ri[i] << endl; } } int T; LL n, k; int main() { init(); cin >> T; while(T--) { scanf("%lld%lld", &n, &k); LL ans = 0; for(int i = 0; i <= k; i++) { LL flag = 1; if((k - i) % 2) flag = -1; LL t = le[i] * ri[k - i] % mod; LL d = fac[k - i] * fac[i] % mod; LL c = fac[k] * Inv(d) % mod; LL x = (t * (1 - fpow(t, n)) % mod) * Inv(1 - t) % mod; if(t == 1) x = n % mod; ans = (ans + flag * c * x ) % mod; ans = (ans + mod) % mod; //cout << t << endl; } ans = (ans * fpow(Inv(trem) % mod, k) + mod) % mod; printf("%lld\n", ans); } return 0; }