牛客练习赛87题解

A

思维题
k = n − 1 k = n - 1 k=n1的时候特判一下就行了
回超 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 
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 nm+1个种选择 ( [ 1 , m ] , [ 2 , m + 1 ] , . . . , [ n − m + 1 , n ] ) ([1,m],[2,m+1],...,[n-m+1,n]) [1,m],[2,m+1],...,[nm+1,n],然后还剩余 n − m n-m nm元素和这1个连续段进行排列,有 ( n − m + 1 ) ! (n-m+1)! (nm+1)!种排列方式,如果 m m m的长度 > 1 >1 >1,还可以选择将连续段翻转或不翻转,因此 m > 1 m>1 m>1时还要乘以2

#include 
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 
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;
}

你可能感兴趣的:(牛客)