A
思维题
当
k
=
n
−
1
k = n - 1
k=n−1的时候特判一下就行了
回超
i
n
t
int
int开
l
o
n
g
l
o
n
g
long long
longlong
B
思维题
找一个数组存一下x左右两边比x小的数有多少个前缀后缀数组的那种
f
o
r
for
for循环
l
l
l
二分
r
r
r
C
d
f
s
dfs
dfs
贪心
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
unordered_map<ll, ll>f;
ll t, n;
ll qmi(ll a, ll k)
{
ll res = 1;
while (k)
{
if (k & 1) res = res * a;
a = a * a;
k >>= 1;
}
return res;
}
ll dfs(ll n)
{
if (n < 6) return n;
if (f.count(n)) return f[n];
ll p1 = 0, p2 = 0;
for (ll i = 1; qmi(6, i)<= n; i ++) p1 ++;
for (ll i = 1; qmi(9, i)<= n; i ++) p2 ++;
return f[n] = min(dfs(n - qmi(6, p1)), dfs(n - qmi(9, p2))) + 1;
}
int main()
{
cin >> t;
while (t -- )
{
cin >> n;
f.clear();
cout << dfs(n) << endl;
}
return 0;
}
D
排列组合
sol的解释:
长度为m的连续段有
n
−
m
+
1
n-m+1
n−m+1个种选择
(
[
1
,
m
]
,
[
2
,
m
+
1
]
,
.
.
.
,
[
n
−
m
+
1
,
n
]
)
([1,m],[2,m+1],...,[n-m+1,n])
([1,m],[2,m+1],...,[n−m+1,n]),然后还剩余
n
−
m
n-m
n−m元素和这1个连续段进行排列,有
(
n
−
m
+
1
)
!
(n-m+1)!
(n−m+1)!种排列方式,如果
m
m
m的长度
>
1
>1
>1,还可以选择将连续段翻转或不翻转,因此
m
>
1
m>1
m>1时还要乘以2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e7 + 5;
const int N = mod = 1e9 + 7;
ll fact[N];
ll n, m ,t;
ll sol(ll n, ll m)
{
if (m > n) return 0;
else
return (n - m + 1) * (fact[n - m + 1]) * (m > 1 ? 2ll: 1ll);
}
int main()
{
cin >> t;
fact[0] = fact[1] = 1;
for (ll i = 2; i < N; i ++ ) fact[i] = fact[i - 1] * i % mod;
while (t -- )
{
cin >> n >> m;
ll ans = fact[n] - sol(n, m + 1) + sol(n, m + 2);
/*
总排列减去不对的再加上多减的
当连续的数字区间大于m的时候就是不对的,
所以假设此时有m+1个连续的数字,把这m+1的数字看成一个数字,和剩余的n-m个数字全排列,得到的一定是不对的
多减的就是发现当有共同连续的数字的时候会被多算一次,
比如假设m+1=3,51234就会被123和234同时减一次,所以我们只需要找到m+2的情况就行,并且此时不用再去重
*/
cout << (ans % mod + mod) %mod << endl;
}
return 0;
}
E
矩阵快速幂
#include <bits/stdc++.h>
using namespace std;
const int N = 60;
typedef long long ll;
int s[N], n, M, x, t;
const int mod = 1e9 + 7;
//矩阵快速幂模板
struct Mat{
ll m[101][101];
};
Mat a, e;
Mat Mul(Mat x, Mat y)
{
Mat c;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ ) c.m[i][j] = 0;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
for (int k = 1; k <= n; k ++ )
c.m[i][j]=(c.m[i][j]%mod+x.m[i][k]*y.m[k][j]%mod)%mod;
return c;
}
Mat pow(Mat x, ll y)
{
Mat ans = e;
while (y){
if (y&1) ans = Mul(x, ans);
x = Mul(x, x);
y >>= 1;
}
return ans;
}
int main()
{
cin >> t;
while (t -- )
{
cin >> n >> x >> M;
for (int i = 1; i <= n; i ++ )
cin >> s[i];
sort(s + 1, s + n + 1);
for (int i = 1; i <= n; i ++ ){
for (int j = n; j > n - i; j -- ) a.m[i][j] = 1;
for (int j = 1; j <= n - i; j ++ ) a.m[i][j] = 0;
}
for (int i = 1; i <= n; i ++ )
e.m[i][1] = s[i];
int t = M / x;
e = pow(a, t + 1);
cout << e.m[n][1] << endl;
}
return 0;
}