来自学长的馈赠5

B. mine

看到题面一头雾水,看到文字版题解一头雾水,看到代码……感觉很显然确实没啥好写的……

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
const int maxn = 1e6 + 10;
const int N = 1e6 + 2;
const ll mod = 1e9 + 7;

char s[maxn];
int n;
ll f[maxn][4];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    scanf("%s", s+1);
    n = strlen(s+1);
    if(s[1] == '?')
    {
        f[1][0] = 1, f[1][1] = 1, f[1][2] = 1;
    }
    else 
    {
        if(s[1] == '*') f[1][2] = 1;
        else f[1][s[1]-'0'] = 1;
    }
    for(int i=2; i<=n; i++)
    {
        if(s[i] == '?')
        {
            f[i][2] = (f[i-1][1]+f[i-1][2])%mod;
            f[i][0] = (f[i-1][0]+f[i-1][2])%mod;
            f[i][1] = (f[i-1][0]+f[i-1][2])%mod;
        }
        else 
        {
            if(s[i] == '*') f[i][2] = (f[i-1][1]+f[i-1][2])%mod;
            if(s[i] == '0') f[i][0] = f[i-1][0];
            if(s[i] == '1') f[i][0] = f[i-1][2], f[i][1] = f[i-1][0];
            if(s[i] == '2') f[i][1] = f[i-1][2];
        }
    }
    printf("%lld\n", (f[n][0]+f[n][2])%mod);
  
    return 0;
}
%%%Delov

 

C. 小凯的疑惑

直接记结论好了gcd(a, b)=1的时候不能用ax+by表示出来的正整数(x和y也是正整数)一共有(a-1)*(b-1)/2个.

我查了半天各种题解并研究了半天,但是终于还是没看懂那些或长篇大论或过分简洁的证明,我表示放弃了。我还是用打表大法来找结论吧。

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
const int maxn = 1507;

int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a%b);
}

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    int x = read(), y = read();
    if(gcd(x, y)!=1) 
    {
        printf("-1\n"); exit(0);
    }
    printf("%lld", 1ll*(x-1)*(y-1)/2);
    
    return 0;
}
View Code

 

D. 排序

二分答案,找到一个尽量大的标准(>=某数)把当前查找的位置上的数包括进去,中间排序的操作用线段树维护,op=0把区间内前小于标准的cnt个数全设为0,其余的全设为1,op=1把区间内大于标准的cnt个数全设为1,其余的全设为0.

二分的模板有两个来自进阶指南,一个是找满足条件的里尽量大的,另一个是找满足条件的里尽量小的,我本来以为要找大于等于的第一个,所以要用求尽量小的答案的模板,但是它不对,然后我忽然发现我枚举的是比大于等于当前数的标准,然后只要当前数在大于等于的范围内是符合条件,所以标准越小越容易满足条件,但是要找恰好的位置,所以这个大于等于的标准应该恰好卡死,也就是说其实要找最大的答案。

不过用像Chen_jr大佬一样的二分模板就不会出现上述问题。

//Cat 对 %%%Chen_jr%%% 的题解情有独钟
#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
const int maxn = 1e5 + 2;
const ll mod = 1e9 + 7;

int n, m, p, a[maxn], now[maxn];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct cat
{
    int op, l, r;
}o[maxn];

struct tree 
{
    struct node 
    {
        int sum, lazy;
    }t[maxn<<2];

    void pushup(int x)
    {
        t[x].sum = t[x<<1].sum + t[x<<1|1].sum;
    }

    void build(int x, int l, int r)
    {
        t[x].sum = t[x].lazy = 0;
        if(l == r)
        {
            t[x].sum = now[l]; return;
        }
        int mid = (l + r) >> 1;
        build(x<<1, l, mid);
        build(x<<1|1, mid+1, r);
        pushup(x);
    }

    void pushdown(int x, int l, int r)
    {
        int ls = x<<1, rs = x<<1|1, mid = (l + r) >> 1;
        if(t[x].lazy == 1)
        {
            t[ls].sum = mid - l + 1;
            t[rs].sum = r - mid;//居然写成了r-l
            t[ls].lazy = t[rs].lazy = 1;
        }
        else 
        {
            t[ls].sum = t[rs].sum = 0;
            t[ls].lazy = t[rs].lazy = -1;
        }
        t[x].lazy = 0;
    }

    void update(int x, int l, int r, int L, int R, int upd)
    {
        if(L > R) return;
        if(L <= l && r <= R)
        {
            if(upd)
            {
                t[x].sum = r - l + 1; t[x].lazy = 1;
            }
            else 
            {
                t[x].sum = 0; t[x].lazy = -1;
            }
            return;
        }
        if(t[x].lazy) pushdown(x, l, r);
        int mid = (l + r) >> 1;
        if(L <= mid) update(x<<1, l, mid, L, R, upd);
        if(R > mid) update(x<<1|1, mid+1, r, L, R, upd);
        pushup(x);
    }

    int query(int x, int l, int r, int L, int R)
    {
        if(L <= l && r <= R)
        {
            return t[x].sum;
        }
        if(t[x].lazy) pushdown(x, l, r);
        int mid = (l + r) >> 1, ans = 0;
        if(L <= mid) ans += query(x<<1, l, mid, L, R);
        if(R > mid) ans += query(x<<1|1, mid+1, r, L, R);
        return ans;
    }
}T;

bool check(int mid)
{
    for(int i=1; i<=n; i++) now[i] = a[i] >= mid ? 1 : 0;
    T.build(1, 1, n);
    for(int i=1; i<=m; i++)
    {
        int cnt = T.query(1, 1, n, o[i].l, o[i].r);
        int u1 = 1, u0 = 0;
        if(o[i].op) swap(u1, u0);
        else cnt = o[i].r - o[i].l + 1 - cnt;
        T.update(1, 1, n, o[i].l, o[i].l+cnt-1, u0);
        T.update(1, 1, n, o[i].l+cnt, o[i].r, u1);
    }
    return T.query(1, 1, n, p, p);
}

int main()
{
    n = read(); m = read();
    for(int i=1; i<=n; i++) a[i] = read();
    for(int i=1; i<=m; i++)
    {
        o[i].op = read(), o[i].l = read(), o[i].r = read();
    }
    p = read();
    int l = maxn, r = -maxn;
    for(int i=1; i<=n; i++)
    {
        l = min(l, a[i]); r = max(r, a[i]);
    }
    while(l < r)
    {
        //printf("l = %d r = %d\n", l, r);
        int mid = (l + r + 1) >> 1;
        if(check(mid)) l = mid;
        else r = mid - 1;
    }
    printf("%d\n", l);
  
    return 0;
}
View Code

 

posted @ 2022-08-19 10:58  Catherine_leah  阅读(102)  评论(0编辑  收藏  举报
/* */