BZOJ 4002 JLOI 2015 有意义的字符串 数列

75 篇文章 1 订阅
19 篇文章 0 订阅

给定正整数 b,d,n ,求

(b+d2)nmod7528443412579576937

其中 0<b2d<(b+1)21018,n1018,bmod2=1,dmod4=1

二项线性递推数列的通项公式是

xn=C1rn+C2sn

递推公式是:
xn=uxn1+vxn2

其中 r,s 是数列特征方程 y2=uy+v 的两根。
而且该特征方程两根是
y=u±u2+4v2


y=A±B2

又题目给定的是 b+d2 ,所以另一根就是 bd2
b,d 的条件 b2d<(b+1)2
bd2(12,0]

同时比对特征方程根式可知:
u=b,v=db24

递推公式得:
xn+2=bxn+1+db24xn

bmod2=1,dmod4=1 ,故 v 为正整数。则xn为整数。
同时:
xn=(b+d2)n+(bd2)n

(b+d2)n=xn(bd2)n

xn 的值可以通过矩阵乘法快速求得。
至于 h(n)=(bd2)n ,当且仅当 bd n 为偶数时1<h(n)<0,故答案减1; bd n 为奇数时0<h(n)<1,对整数部分无影响。

3个0ms是怎么写的。。为了上第一页真是豁出去了233。

#include <cstdio>
#define rep(i,j,k) for(int i=j;i<k;i++)
typedef unsigned long long ull;
const ull MOD = 7528443412579576937ll;
inline void add(ull &a, ull b) { a += b; if (a > MOD) a -= MOD; }
inline ull mul(ull a, ull b) {
 ull x = 0; for (; b; add(a, a), b >>= 1) if(b & 1) add(x, a); return x;
}
struct Matrix {
 ull c[2][2];
 Matrix(int x = 0) { c[0][1] = c[1][0] = 0; rep(i,0,2) c[i][i] = x; }
 Matrix operator * (const Matrix& a) const {
  Matrix z;
  rep(i,0,2) rep(j,0,2) rep(k,0,2) z.c[i][j] = (z.c[i][j] + mul(c[i][k], a.c[k][j])) % MOD;
  return z;
 }
 friend Matrix operator ^(Matrix a, ull p) {
  Matrix v(1); for (; p; a = a * a, p >>= 1) if(p & 1) v = a * v; return v;
 }
} a;
int main() {
 long long b, d, n, ans;
 scanf("%lld%lld%lld", &b, &d, &n);
 if (n == 0) ans = 1;
 else {
  a.c[0][0] = b; a.c[0][1] = d - b * b >> 2; a.c[1][0] = 1;
  a = a ^ (n - 1); ans = (mul(a.c[0][0], b) + mul(a.c[0][1], 2)) % MOD;
  if (d != b * b && n % 2 == 0) ans -= 1;
 }
 return printf("%lld\n", ans), 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值