超级码力在线编程大赛初赛 第3场

A、最大公倍数

是一个结论题吧。
b b 是奇数的时候,那么答案肯定是 b ( b 1 ) ( b 2 ) b*(b-1)*(b-2) ,因为他们两两互质。
然后当 b a = = 2 b-a==2 时,直接求一个lcm。
否则就是偶数:偶数的话如果是3的倍数,答案就是 ( b 1 ) ( b 2 ) ( b 3 ) (b-1)*(b-2)*(b-3) ,否则b-1,就变成奇数的情况了。

class Solution {
public:
    /**
     * @param a: Left margin
     * @param b: Right margin
     * @return: return the greatest common multiple
     */
    #define ll long long
    template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
    template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
    else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
    ll greatestcommonmultiple(int a, int b) {
        // write your code here
        ll res = 0;
        if(b&1)res = 1ll*b*(b-1)*(b-2);
        else if(b-a==2){
            res = lcm(b,lcm(b-1,b-2));
        }else{
            if(b%3!=0)res = 1ll*b*(b-1)*(b-3);
            else res =  1ll*(b-1)*(b-2)*(b-3);
        }
        return res;
    }
    ll lcm(int a,int b){
        return 1ll*a*b/gcd(a,b);
    }
};

B、房屋染色

定义 d p [ i ] [ j ] [ k ] dp[i][j][k] 表示以 i i 结尾颜色为 j j 且是否已有步行街的最小代价 ( 0 k 1 ) (0≤k≤1)
然后维护一个前缀和,那么转移就是
只移动一步。
d p [ i + 1 ] [ k ] [ 0 ] = m i n ( d p [ i + 1 ] [ k ] [ 0 ] , d p [ i ] [ j ] [ 0 ] + c o s t s [ i + 1 ] [ k ] ) ; dp[i+1][k][0] = min(dp[i+1][k][0],dp[i][j][0]+costs[i+1][k]);
d p [ i + 1 ] [ k ] [ 1 ] = m i n ( d p [ i + 1 ] [ k ] [ 1 ] , d p [ i ] [ j ] [ 1 ] + c o s t s [ i + 1 ] [ k ] ) ; dp[i+1][k][1] = min(dp[i+1][k][1],dp[i][j][1]+costs[i+1][k]);
有步行街。
d p [ i + p ] [ k ] [ 1 ] = m i n ( d p [ i + p ] [ k ] [ 1 ] , d p [ i ] [ k ] [ 0 ] + v a [ i + p ] [ k ] v a [ i ] [ k ] ) ; dp[i+p][k][1] = min(dp[i+p][k][1],dp[i][k][0]+va[i+p][k]-va[i][k]);

class Solution {
public:
    /**
     * @param costs: costs of paint ith house into color j
     * @param t: maximum length of street
     * @return: minimum costs of painting all houses
     */
    long long va[105][105];
    long long dp[105][105][2];
    int paintHouseIII(vector<vector<int>> &costs, int t) {
        // Write your code here.
        int n = costs.size(),m = costs[0].size();
        for(int i = 0;i < m;++i){
            for(int j = 0;j < n;++j){
                if(j==0)va[j][i] = costs[j][i];
                else va[j][i] = va[j-1][i] + costs[j][i];
               // cout<<j<<" "<<i<<" " << va[j][i]<<endl;
                dp[j][i][0] = dp[j][i][1] = INT_MAX;
            }
        }
        for(int i = 0;i < m;++i)dp[0][i][0] = dp[0][i][1] = costs[0][i];
        for(int i = 0;i < n;++i){
            for(int j = 0;j < m;++j){
                for(int k = 0;k < m;++k){
                    if(j==k){
                        for(int p = 0;p < t;++p){
                            if(i+p>=n)break;
                            dp[i+p][k][1] = min(dp[i+p][k][1],dp[i][k][0]+va[i+p][k]-va[i][k]);
                        }
                        continue;
                    }
                    if(i+1<n){
                        dp[i+1][k][0] = min(dp[i+1][k][0],dp[i][j][0]+costs[i+1][k]);
                        dp[i+1][k][1] = min(dp[i+1][k][1],dp[i][j][1]+costs[i+1][k]);
                    }
                }
            }
        }
        long long res = INT_MAX;
        for(int i = 0;i < m;++i)res = min(res,min(dp[n-1][i][1],dp[n-1][i][0]));
        return res;
    }
};

字符串游戏

抽象为 逆Nim 博弈
Nim 博弈:两个人玩游戏,有 n 堆石子,每次操作可以选一堆石子xjb拿,最少拿一颗,无子可取者为负。
在这里插入图片描述

class Solution {
public:
    /**
     * @param s: a string for this game 
     * @return: return whether Alice can win this game
     */
    bool stringGame(string &s) {
        // Write your code here.
        int num[30] = {0};
        for(int i = 0;i < s.size();++i){
            num[s[i]-'a']++;
        }
        int res = 0;
        bool f= 1,f1 = 0;
        for(int i = 0;i < 26;++i){
            if(!num[i])continue;
            res ^= num[i];
            if(num[i]!=1)f = 0;
            if(num[i]>1)f1 = 1;
        }
        if(f&&!res||f1&&res)return true;
        else return false;
    }
};

完美字符串

直接选取连续的0,然后最大限度的翻转它就ok了,即当有连续5个0,k=3,那么需要翻转2次。

class Solution {
public:
    /**
     * @param s: string need to be transformed
     * @param k: minimum char can be transformed in one operation
     * @return: minimum times of transforming all char into '1'
     */
    int perfectString(string &s, int k) {
        long long res = 0;
        int i = 0,len,j;
        while(i < s.size()){
            if('1'==s[i]){i++;continue;}
            j = i;
            while(j<s.size()&&s[j]=='0')++j;
            len = j-i;
            res += len/k;
            if(len%k)res++;
            i = j;
        }
        return res;
    }
}a;

猜你喜欢

转载自blog.csdn.net/weixin_43571920/article/details/108418320
今日推荐