马蹄集(第二十七周)

第一题“越狱”

知识点一:快速幂

马蹄集(第二十七周)_第1张图片

首先理解快速幂:

马蹄集(第二十七周)_第2张图片

但是会显示超时,于是翻一下之前的题目???等一会做,目前要把这几道题做完

# 用总方案数-不会越狱的方案数

def main():
    # code here
    m, n = map(int, input().split())
    sum_sort = fastpow(m,n, 1007)
    sum_unsuccess=1
    flag = 1
    if m>1007:
        che=m%1007
    else:
        che=m
    sum_unsuccess=(che*fastpow(m-1,n-1,1007))%1007

    return sum_sort - sum_unsuccess

def fastpow(a, n, mod):
    base = a
    res = 1  # 用res返回结果
    while (n):

        if (n & 1):  # 如果n的最后一位是1,表示这个地方需要乘
            res = (res * base) % mod
        base = (base * base) % mod  # 推算乘积:a² --> (a²)² -->((a²)²)² ...
        n >>= 1

    return res

if __name__ == '__main__':
    result = main()%1007
    print(result)

第二道题目:盒子与球

知识点:动态规划

马蹄集(第二十七周)_第3张图片

首先考虑当盒子相同的时候,然后盒子不同就 * r!

1、dp[i][j]:表示前i个球放在了j个盒子里

2、dp[i][j] = {dp[i-1][j]*j;第i个球放在了前面的重复的盒子,即前i-1个球已经把j个盒子放满了。

                  + dp[i-1][j-1];第i个球放在了一个不一样的盒子,即前i-1个球只把j-1个盒子装满。}

3、当dp[1][1] =1;dp[2][1]=1;dp[2][2] = 2;当j = 1的时候dp =1;并且i>j

代码:

n,r=map(int,input().split());
# print(m,n)
x = max(r,n)
dp =[[0 for i in range(x+1)] for j in range(x+1)]
dp[0][0] =1

for i in range(1,x+1):
    for j in range(1,x+1):
        dp[i][j] = dp[i-1][j] * j + dp[i-1][j-1]
a = dp[n][r]
for i in range(1,r+1):
     a *= i
print(a)

第三道题:Square

知识点:组合数学

马蹄集(第二十七周)_第4张图片这是一个排列组合的问题:首先我们一定知道答案:C 上n下(m+n) =(m+n)!/n!m!;秘籍在于把他们分解为小质数因子的乘积。

????有点难下一个题目

#include 

using namespace std;
const int N = 1e5 + 7;
const int N2 = 107;

int n,m;
int fac[N],a[N2] = {1}, c[N2];

void clear(int a[]){//字符串清零
    for (int i = 0; i < N2; i++){ 
        a[i] = 0;
    }
}

void mul_short(int a[], int b, int c[]){//a*b=c,高精度*单精度
    clear(c);
    for(int i = 0; i < N2; i++){
        c[i] += a[i] * b;
        if(c[i] >= 10){
            c[i + 1] += c[i] / 10;
            c[i] %= 10;
        }
    }
}

int main( )
{
    cin >> m >>n;
    n = n + m;
    //C(m,n)
    //处理 n*(n - 1)*...*(n-m+1)
    for(int i = n - m + 1; i <= n; i++){
        int tmp = i;
        for(int j = 2; j * j <= tmp;j++){
            while( tmp % j == 0){
                fac[j] ++;
                tmp /= j;
            }
        }
        if(tmp > 1){
            fac[tmp]++;
        }
    }
    //处理 m!
    for(int i = 1; i <= m; i++){
        int tmp = i;
        for(int j = 2; j * j <= tmp;j++){
            while( tmp % j == 0){
                fac[j] --;
                tmp /= j;
            }
        }
        if(tmp > 1){
            fac[tmp]--;
        }
    }
    for(int i = 2; i < N; i++){
        while(fac[i]--){
            mul_short(a,i,c); 
            memcpy(a,c,sizeof(c));
        }
    }
    for(int i = 99; i >= 0; i--){
        if(i % 10 == 0){
            cout << a[i] << endl;
        }else{
            cout << a[i];
        }
    }
    return 0;
}

第四题:找朋友

马蹄集(第二十七周)_第5张图片

最少的朋友对数:前m-1个组每组一个人,最后一组有n-(m-1) = x个人,那么也就是x(x-1)/2

最多的朋友对数:n / m = ?  前x组有这么多人,后面这么多人

代码:

第五题目:点菜

马蹄集(第二十七周)_第6张图片

极限是每个菜都点了两次a+b+c = 2*总数

你可能感兴趣的:(算法,数据结构)