leetcode 第44场双周赛 题解

找到最高海拔
思路:前缀和一下,恢复原来的序列,然后维护个max即可

class Solution {
    
    
public:
    int largestAltitude(vector<int>& gain) {
    
    
        int ma=0,now=0;
        for(auto &x:gain){
    
    
            now+=x;
            ma=max(ma,now);
        }
        return ma;
    }
};

需要教语言的最少人数
思路:首先先统计出来每个人会的语言,a[i][j]=1表示第i个人会第j门语言。
然后枚举每一种语言即可,维护一个min,复杂度n^3
用个vector存下来都有谁学了当前这个语言
注意每次结束后把新学的人的语言给去掉。

class Solution {
    
    
public:
    
    int minimumTeachings(int n, vector<vector<int>>& l, vector<vector<int>>& f) {
    
    
        int ans=505;
        int a[505][505]={
    
    0};
         for(int j=0;j<l.size();j++){
    
    
            for(int k=0;k<l[j].size();k++){
    
    
                    a[j+1][l[j][k]]=1;
            }
        }
        
        for(int i=0;i<=n;i++){
    
    
            vector<int> an;
            for(int j=0;j<f.size();j++){
    
    
                int F=0;
                for(int k=1;k<=n;k++){
    
    
                    if(a[f[j][0]][k] && a[f[j][1]][k]){
    
    
                        F=1;
                        break;
                    }
                }
                if(F==0){
    
    
                    if(a[f[j][0]][i]) a[f[j][1]][i]=1,an.push_back(f[j][1]);
                    else if(a[f[j][1]][i]) a[f[j][0]][i]=1,an.push_back(f[j][0]);
                    else a[f[j][1]][i]=1,a[f[j][0]][i]=1,an.push_back(f[j][1]),an.push_back(f[j][0]);    
                }
            }
            ans=min(ans,(int)an.size());
            for(auto &X:an){
    
    
                a[X][i]=0;
            }
            
        }
        return ans;
    }
};

解码异或后的排列
思路:算是个思维题吧。注意一下数据,n为奇数。那么他给出的序列长度就是偶数,很明显肯定和xor的性质有关。
我们对给的序列尝试一下前缀xor。
可以得到序列就变成了
a[1] ^ a[2] a[1] ^ a[3] a[1] ^ a[4] … a[1] ^ a[n]
我们对前缀异或在全部异或一下得到 (假设n为5)
x =
a[1] ^ a[2] ^ a[1] ^ a[3] ^ a[1] ^ a[4] ^ a[1] ^ a[5] =
a[2] ^ a[3] ^ a[4] ^ a[5]

等于除了a[1]以外的其他数字的xor值我们都求出来了。
因为知道n的值,我们可以求一下z = 1 ^ 2 ^ 3 ^ 4 ^5 … ^ n
那么把 x xor z 就得到a[1]的值了,因为除了a[1] 其他数字都出现了两遍。
这样只需要把a[1] 与 前缀异或序列 在xor一下,就能得到a[2] a[3]…a[n]的值了

class Solution {
    
    
public:
    vector<int> decode(vector<int>& e) {
    
    
        int x=0;
        for(int i=1;i<e.size();i++) e[i]^=e[i-1];
        for(auto &y:e) x^=y;
        int z=0;
        for(int i=1;i<=e.size()+1;i++) z^=i;
        vector<int> ans;
        ans.push_back(z^x);
        for(int i=0;i<e.size();i++) ans.push_back(ans[0]^e[i]);
        return ans;
        
    }
};

生成乘积数组的方案数
思路:很容易看出来是个球盒模型。乘积容易想到质因数分解。
所以对于同一种质因子放到盒子里,其实就是球相同,盒子不同。
也就是隔板法即可。

隔板法公式为C(n+m-1,m-1) n为球的个数,m为盒子的个数。
但是这题n、m为1e4,范围很大,空间开不下?
注意到2 ^ 14 > 1e4 ,也就是球的个数其实就十几个。
那么我们知道C(n,m)=C(n,n-m)
所以C(n+m-1,m-1)=C(n+m-1,n+m-1-(m-1))=C(n+m-1,n)
我们可以用杨辉三角预处理出来组合数 其中第二维只需要到13即可。

typedef long long ll;
const ll mod=1e9+7;
ll dp[10055][15];
class Solution {
    
    
public:
    vector<int> ans;
    vector<int> waysToFillArray(vector<vector<int>>& q) {
    
    
        dp[0][0]=1;
        for(int i=1;i<10050;i++){
    
    
            dp[i][0]=1;
            for(int j=1;j<14;j++){
    
    
                dp[i][j]=(dp[i-1][j]+dp[i-1][j-1])%mod;
            }
        }

        for(auto &X:q){
    
    
            ll now=1;
            int m=X[0],x=X[1];
            for(int i=2;i*i<=x;i++){
    
    
                if(x%i==0){
    
    
                    int n=0;
                    while(x%i==0) ++n,x/=i;
                    now*=dp[n+m-1][n];//C(n+m-1,m-1)=C(n+m-1,n)
                    now%=mod;
                }
            }
            if(x!=1){
    
    
                now*=dp[1+m-1][1];
                now%=mod;
            }
            ans.push_back(now);
        }
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_43563669/article/details/113093006