T1:Sequence
title
solution
一眼就是很裸的矩阵加速
\(\lfloor\frac{p}{l}\rfloor\)分块矩阵加速就可以了
\[\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} \]
这道题唯一算得上是坑的应该是\(n,p\)的大小,当\(p/l==0\)直接矩阵加速到底即可,注意\(r\)不能超过\(n\)
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=1}^nd−((a_i−1)\%d+1)≤k \]
扫描二维码关注公众号,回复:
11249440 查看本文章
\[=\sum_{i=1}^nd-\sum_{i=1}^n(a_i-1-\lfloor\frac{a_i-1}{d}\rfloor*d+1)\le k \]
\[=n*d-\sum_{i=1}^na_i+\sum_{i=1}^n\lfloor\frac{a_i-1}{d}\rfloor*d\le k \]
\[d(n+\sum_{i=1}^n\lfloor\frac{a_i-1}{d}\rfloor*d)\le k+\sum_{i=1}^na_i \]
\(\lfloor\frac{a_i-1}{d}\rfloor\)有根号的取值,我们直接分块即可
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;
}