1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> using namespace std;
typedef long long ll; struct Matrix{ ll m[4][4]; }tree[400005]; ll mod = 1000000007;
ll a[100005]; Matrix mul(Matrix a, Matrix b) { Matrix tmp; memset(tmp.m,0,sizeof(tmp.m)); for(int i = 1;i <= 2; ++i) { for(int j = 1; j <= 2; ++j) { for(int k = 1; k <= 2; ++k) { tmp.m[i][j] = (tmp.m[i][j] + a.m[i][k] * b.m[k][j]) % mod; } } } return tmp; }
void build(int node, int l ,int r) { if(l == r) { tree[node].m[1][1] = 1; tree[node].m[1][2] = a[l] % mod; tree[node].m[2][1] = 1; tree[node].m[2][2] = 0; return ; } int mid = (l + r) >> 1; build(node << 1, l ,mid); build(node << 1|1,mid + 1 , r); tree[node]= mul(tree[node << 1|1] , tree[node << 1]); }
Matrix query(int node, int begin , int end, int l, int r) { if(l <= begin && end <= r) { return tree[node]; } int mid = (begin + end) >> 1; if(r <= mid) return query(node << 1 , begin, mid, l , r); else if(l > mid ) return query(node << 1|1, mid + 1, end, l, r); else return mul(query(node << 1|1,mid + 1, end, l, r),query(node << 1,begin, mid, l, r)); }
int main() { int T,n,Q; cin >> T; while(T--) { scanf("%d %d",&n,&Q); for(int i = 1; i <= n; ++i) { scanf("%lld",&a[i]); } build(1,1,n); while(Q--) { int L,R; scanf("%d %d",&L,&R); if(R - L < 2) { printf("%d\n",a[R] % mod); } else{ Matrix c = query(1,1,n,L + 2, R); printf("%lld\n",(c.m[1][1] * a[L + 1] + c.m[1][2] * a[L]) % mod); } } } }
|