文章目录
- T1:Sequence
- title
- solution
- T2:Bamboo Partition
- title
- solution
- code
T1:Sequence
title
传送
solution
一眼就是很裸的矩阵加速
⌊pl⌋\lfloor\frac{p}{l}\rfloor⌊lp⌋分块矩阵加速就可以了
[BA1]×[DC⌊pl⌋010001]\begin{bmatrix} B\\ A\\ 1\\ \end{bmatrix} \times \begin{bmatrix} D&C&\lfloor\frac{p}{l}\rfloor\\ 0&1&0\\ 0&0&1 \end{bmatrix} ⎣⎡BA1⎦⎤×⎣⎡D00C10⌊lp⌋01⎦⎤
这道题唯一算得上是坑的应该是n,pn,pn,p的大小,当p/l==0p/l==0p/l==0直接矩阵加速到底即可,注意rrr不能超过nnn
## code
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
#define mod 1000000007
struct Matrix {ll c[5][5];void init() {memset( c, 0, sizeof( c ) );}Matrix operator * ( const Matrix &a ) {Matrix ans;ans.init();for( int i = 1;i <= 3;i ++ )for( int j = 1;j <= 3;j ++ )for( int k = 1; k <= 3;k ++ )ans.c[i][j] = ( ans.c[i][j] + c[i][k] * a.c[k][j] ) % mod;return ans;}
}V;
ll T, A, B, C, D, P, n;
ll ans1, ans2;Matrix qkpow( Matrix a, int b ) {Matrix ans;ans.init();for( int i = 1;i <= 3;i ++ ) ans.c[i][i] = 1;while( b ) {if( b & 1 ) ans = ans * a;a = a * a;b >>= 1;}return ans;
}signed main() {scanf( "%lld", &T );while( T -- ) {scanf( "%lld %lld %lld %lld %lld %lld", &A, &B, &C, &D, &P, &n );if( n == 1 ) { printf( "%lld\n", A ); continue; }if( n == 2 ) { printf( "%lld\n", B ); continue; }ans1 = B, ans2 = A;for( int l = 3, r;l <= n;l = r + 1 ) {if( P / l == 0 ) {V.init();V.c[1][1] = D, V.c[1][2] = C;V.c[2][1] = V.c[3][3] = 1;V = qkpow( V, n - l + 1 );ans1 = ( V.c[1][1] * ans1 % mod + V.c[1][2] * ans2 % mod + V.c[1][3] ) % mod;ans2 = ( V.c[2][1] * ans1 % mod + V.c[2][2] * ans2 % mod + V.c[2][3] ) % mod;break;}r = min( n, P / ( P / l ) );V.init();V.c[1][1] = D, V.c[1][2] = C, V.c[1][3] = P / l;V.c[2][1] = V.c[3][3] = 1;V = qkpow( V, r - l + 1 );ll newans1 = ( V.c[1][1] * ans1 % mod + V.c[1][2] * ans2 % mod + V.c[1][3] ) % mod;ll newans2 = ( V.c[2][1] * ans1 % mod + V.c[2][2] * ans2 % mod + V.c[2][3] ) % mod;ans1 = newans1, ans2 = newans2;}printf( "%lld\n", ans1 );} return 0;
}
T2:Bamboo Partition
title
传送门
solution
∑i=1nd−((ai−1)%d+1)≤k∑_{i=1}^nd−((a_i−1)\%d+1)≤ki=1∑nd−((ai−1)%d+1)≤k
=∑i=1nd−∑i=1n(ai−1−⌊ai−1d⌋∗d+1)≤k=\sum_{i=1}^nd-\sum_{i=1}^n(a_i-1-\lfloor\frac{a_i-1}{d}\rfloor*d+1)\le k=i=1∑nd−i=1∑n(ai−1−⌊dai−1⌋∗d+1)≤k
=n∗d−∑i=1nai+∑i=1n⌊ai−1d⌋∗d≤k=n*d-\sum_{i=1}^na_i+\sum_{i=1}^n\lfloor\frac{a_i-1}{d}\rfloor*d\le k=n∗d−i=1∑nai+i=1∑n⌊dai−1⌋∗d≤k
d(n+∑i=1n⌊ai−1d⌋∗d)≤k+∑i=1naid(n+\sum_{i=1}^n\lfloor\frac{a_i-1}{d}\rfloor*d)\le k+\sum_{i=1}^na_id(n+i=1∑n⌊dai−1⌋∗d)≤k+i=1∑nai
⌊ai−1d⌋\lfloor\frac{a_i-1}{d}\rfloor⌊dai−1⌋有根号的取值,我们直接分块即可
code
#include <cstdio>
#include <iostream>
using namespace std;
#define N 105
#define int long long
int n, k, Max, ans;
int a[N];signed main() {scanf( "%lld %lld", &n, &k );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &a[i] ), k += a[i], Max = max( Max, a[i] - 1 );for( int l = 1, r, sum;l <= Max;l = r + 1 ) {r = Max, sum = 0;for( int i = 1;i <= n;i ++ )if( a[i] - 1 >= l ) {sum += ( a[i] - 1 ) / l;r = min( r, ( a[i] - 1 ) / ( ( a[i] - 1 ) / l ) );}if( l <= k / ( sum + n ) ) ans = max( ans, min( k / ( sum + n ), r ) );}if( Max < k / n ) ans = max( ans, k / n );printf( "%lld", ans );return 0;
}