【牛客练习赛59】 A【DP】B【思维】C【三分】D【记忆化搜索】

文章目录

  • A
  • B
  • C
  • D

A

思路:很经典的题目了,不仅可以判定是否有这样的子序列,同时还可以找到有多少这样的子序列。
Code:

#include 
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int N = 1e5 + 11;
const int M = 1e6 + 11;
const int MOD = 1e9 + 7;

int XiaoQiao[20], Xiaohuihui[32];

int cnt[N];
char s1[] = "XiaoQiao";
char s2[ ] = "XiaoHuiHui";

bool deal(char *ss, string s){
    memset(cnt, 0, sizeof(cnt));
    int len = strlen(ss);
    cnt[len ] = 1;
    for(int i = s.size() - 1; i >= 0; i--){
        for(int j = 0; ss[j]; j++) {
            if(s[i] == ss[j]) {
                if(cnt[j + 1] > 0)
                    cnt[j] = 1;
            }
        }
    }
    return cnt[0] > 0;
}

int main(int argc, char **args){
    string s; cin >>s;
    if(deal(s1, s) && deal(s2, s)) puts("Happy");
    else puts("emm");
return 0;
}

B

思路:将题目中给的公式,进行化简就行了。
Code:

#include 
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int N = 1e5 + 11;
const int M = 1e6 + 11;
const int MOD = 1e9 + 7;

ll c[N];
int main(int argc, char **args){
    int n; scanf("%d", &n);
    for(int i = 0; i < n; i++){
        int a,b; scanf("%d%d", &a, &b);
        c[i] = b * 1ll * (a - b) * (a - b);
    }
    sort(c, c + n);
    ll ans = 0;
    for(int i = 1; i < n; i++){
        ans += c[i] - c[i - 1];
    }
    printf("%lld\n", ans);
return 0;
}

C

思路:一共就两种合成装备的方式,所以我们枚举其中一个方式的次数,同时从直觉上看,如果全是某一种方式,结果不一定最优,应该是在某个中间,两种组合取得平衡,组合装备数量最多。所以问题转化为了,一个有极小值的问题,这种问题可以用三分解决。
Code:

#include 
using namespace std;
  
typedef long long ll;
typedef pair<int, int> pii;
  
const int N = 1e5 + 11;
const int M = 1e6 + 11;
const int MOD = 1e9 + 7;
  
ll x, y;
ll get(ll n){
    return min((x - 4 * n  ) / 2, (y - n ) / 3);
}
 
ll f(ll mid){
    if(4 * mid > x || mid > y) return 0;
    return mid + get(mid);
}
 
int main(int argc, char **args){
    int t; scanf("%d", &t);
    while(t--){
        scanf("%lld%lld", &x, &y);
         
        ll L, R, mid, midr;
        L = 0, R = min(x / 4, y);
        while(L + 2 < R){
            mid = (L + R) / 2;
            midr = (mid + R) / 2;
            if(f(mid) > f(midr)) R = midr;
            else L = mid;
        }
        mid = (L + R ) / 2;
        printf("%lld\n", max(max(f(L), f(R)), f(mid)));
    }
return 0;
}

D

思路:直接记忆化搜索。
Code:

#include 
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int N = 1e5 + 11;
const int M = 1e6 + 11;
const int MOD = 1e9 + 7;

map<ll, int> mp;  // 因为值大,所以用了map来记忆历史值

int solve(ll n){
   if(mp[n]) return mp[n];
    if(2==solve(n / 2) || 2==solve(n - n / 2)) mp[n] = 1;
    else mp[n] = 2;
    return mp[n];  
} 
int main(int argc, char **args){
    int t; scanf("%d", &t);
    while(t--){  
        mp.clear();
        mp[1] = 2;
        mp[2] = 1;
        mp[3] = 1;
        mp[4] = 2;
        ll n; scanf("%lld", &n);
        puts((solve(n) == 1)? "XiaoHuiHui" :"XiaoQiao");
    }
return 0;
}

你可能感兴趣的:(思维,总是不会的DP,各种比赛)