zoukankan      html  css  js  c++  java
  • 2018.10.20 XMYZ Day1总结

    上周的忘写了……题目没有作者……

    T1.backpack

    期望得分100,实际得分100.

    感觉我自己真是不如以前了……以前做这种题都是秒掉的,现在怎么想了10分钟啊……

    因为物品的体积和价值都非常小,我们有一句套话,“远距离贪心,近距离暴力”,所以虽然背包的体积特别大,我们可以把他压缩成1000000左右,剩下的直接暴力取性价比最高的即可。

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<queue>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 10000005;
    const int INF = 1000000009;
    const ll mod = 1e9+7;
    
    ll read()
    {
        ll ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    
    ll dp[M],m,n,a[M],b[M],v[105],mpos,ans;
    double maxn;
    
    void solve1()
    {
        rep(i,1,n)
        rep(j,a[i],m) dp[j] = max(dp[j],dp[j-a[i]] + b[i]);
        printf("%lld
    ",dp[m]);
    }
    
    int main()
    {
        freopen("backpack.in","r",stdin);
        freopen("backpack.out","w",stdout);
        n = read(),m = read();
        rep(i,1,n) 
        {
            a[i] = read(),b[i] = read();
            v[a[i]] = max(b[i],v[a[i]]);
        }
        if(n <= 10000 && m <= 10000) solve1();
        else
        {
            rep(i,1,100)
            {
                double p = (double)(i),q = (double)(v[i]);
                if(q / p > maxn) maxn = q / p,mpos = i;
            }
            if(m > 100000)
            {
                ll k = (m - 100000) / mpos;
                m -= k * mpos,ans += k * v[mpos];
            }
            rep(i,1,100)
            rep(j,i,m) dp[j] = max(dp[j],dp[j-i] + v[i]);
            ans += dp[m];
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    T2.sort

    期望得分20,实际得分0.

    这道题考试的时候没怎么想,主要刚T3了,而且我也不会求方案数。写了个爆搜,然后GG了。

    后来想到这个最大值和最小值很好维护,最大值取后一半减去前一半即可,而最小值的话只要奇偶分别维护取差值即可。这个可以使用线段树分别维护奇偶,稍微有点麻烦,下放的时候有很多特判。

    之后至于方案数,mrclr大佬说,你可以把它看成一个括号序列匹配,就是一个卡特兰数。求一下阶乘和阶乘的逆元即可。

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<queue>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 500005;
    const int INF = 1000000009;
    const ll mod = 1e9+7;
    
    ll read()
    {
        ll ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    
    struct seg
    {
        ll v,ov,ev,lazy;
    }t[M<<3];
    
    ll n,m,c[M<<1],l,r,op,val,sum[M<<1],inv[M<<1];
    
    ll qpow(ll a,ll b)
    {
        ll p = 1;
        while(b)
        {
            if(b&1LL) p *= a,p %= mod;
            a *= a,a %= mod;
            b >>= 1LL;
        }
        return p;
    }
    
    void init()
    {
        sum[0] = inv[0] = inv[1] = 1ll;
        rep(i,1,n<<1) sum[i] = sum[i-1] * i,sum[i] %= mod;
        inv[n<<1] = qpow(sum[n<<1],mod-2);
        per(i,(n<<1)-1,1) inv[i] = inv[i+1] * (i+1),inv[i] %= mod;
        //rep(i,1,n<<1) printf("%lld ",sum[i]);enter;
    }
    
    void pushup(int p)
    {
        t[p].v = t[p<<1].v + t[p<<1|1].v,t[p].v %= mod;
        t[p].ev = t[p<<1].ev + t[p<<1|1].ev,t[p].ev %= mod;
        t[p].ov = t[p<<1].ov + t[p<<1|1].ov,t[p].ov %= mod;
    }
    
    void pushdown(int p,int l,int r)
    {
        ll mid = (l+r) >> 1,k = mid - l + 1,q = r - mid;
        t[p<<1].v += t[p].lazy * k,t[p<<1].v %= mod;
        t[p<<1|1].v += t[p].lazy * q,t[p<<1|1].v %= mod;
        t[p<<1].lazy += t[p].lazy,t[p<<1|1].lazy += t[p].lazy;
        t[p<<1].lazy %= mod,t[p<<1|1].lazy %= mod;
        if(k & 1)
        {
            if(l&1) t[p<<1].ov += t[p].lazy * (k + 1 >> 1),t[p<<1].ev += t[p].lazy * (k>>1);
            else t[p<<1].ov += t[p].lazy * (k >> 1),t[p<<1].ev += t[p].lazy * (k + 1 >> 1);
        }
        else t[p<<1].ov += t[p].lazy * (k >> 1),t[p<<1].ev += t[p].lazy * (k >> 1);
        t[p<<1].ov %= mod,t[p<<1].ev %= mod;
        if(q & 1)
        {
            if((mid + 1) & 1) t[p<<1|1].ov += t[p].lazy * (q + 1 >> 1),t[p<<1|1].ev += t[p].lazy * (q >> 1);
            else t[p<<1|1].ov += t[p].lazy * (q >> 1),t[p<<1|1].ev += t[p].lazy * (q + 1 >> 1);
        }
        else t[p<<1|1].ov += t[p].lazy * (q >> 1),t[p<<1|1].ev += t[p].lazy * (q >> 1);
        t[p<<1|1].ov %= mod,t[p<<1|1].ev %= mod;
        t[p].lazy = 0;
    }
    
    void build(int p,int l,int r)
    {
        if(l == r) 
        {
            t[p].v = c[l];
            if(l & 1) t[p].ov = c[l];
            else t[p].ev = c[l];
            return;
        }
        int mid = (l+r) >> 1;
        build(p<<1,l,mid),build(p<<1|1,mid+1,r);
        pushup(p);
    }
    
    void modify(int p,int l,int r,int kl,int kr,ll val)
    {
        if(l == kl && r == kr) 
        {
            ll k = r - l + 1;
            t[p].v += val * k,t[p].lazy += val;
            t[p].v %= mod,t[p].lazy %= mod;
            if(k & 1)
            {
                if(l & 1) t[p].ov += val * (k + 1 >> 1),t[p].ev += val * (k >> 1);
                else t[p].ov += val * (k >> 1),t[p].ev += val * (k + 1 >> 1);
            }
            else t[p].ov += val * (k >> 1),t[p].ev += val * (k >> 1);
            t[p].ov %= mod,t[p].ev %= mod;
            return;
        }
        if(t[p].lazy) pushdown(p,l,r);
        int mid = (l+r) >> 1;
        if(kr <= mid) modify(p<<1,l,mid,kl,kr,val);
        else if(kl > mid) modify(p<<1|1,mid+1,r,kl,kr,val);
        else modify(p<<1,l,mid,kl,mid,val),modify(p<<1|1,mid+1,r,mid+1,kr,val);
        pushup(p);
    }
    
    ll query(int p,int l,int r,int kl,int kr,int f)
    {
        if(l == kl && r == kr) 
        {
            if(f == 1) return t[p].v;
            else if(f == 2) return t[p].ov;
            else if(f == 3) return t[p].ev;
        }
        ll mid = (l+r) >> 1;
        if(t[p].lazy) pushdown(p,l,r);
        if(kr <= mid) return query(p<<1,l,mid,kl,kr,f);
        else if(kl > mid) return query(p<<1|1,mid+1,r,kl,kr,f);
        else return query(p<<1,l,mid,kl,mid,f) + query(p<<1|1,mid+1,r,mid+1,kr,f) % mod;
    }
    
    int main()
    {
        freopen("sort.in","r",stdin);
        freopen("sort.out","w",stdout);
        n = read(),m = read();
        init();
        rep(i,1,n<<1) c[i] = read();
        build(1,1,n<<1);
        rep(i,1,m)
        {
            op = read();
            if(op == 0) l = read(),r = read(),val = read(),modify(1,1,n<<1,l,r,val);
            else
            {
                l = read(),r = read();
                int g = (l + r) >> 1,h = (r - l + 1) >> 1;
                ll a = query(1,1,n<<1,l,g,1),b = query(1,1,n<<1,g+1,r,1),maxx = (b - a + mod << 1) % mod;
                ll ka = query(1,1,n<<1,l,r,2),kb = query(1,1,n<<1,l,r,3),minx = abs(kb - ka) % mod;
                ll cat = sum[h << 1] * inv[h] % mod * inv[h+1] % mod;
                printf("%lld %lld %lld
    ",maxx >> 1,minx,cat);
            }
        }
        return 0;
    }
    View Code

    T3.digit

    期望得分20,实际得分20.

    考试的时候主要刚这题了……想到使用dp[i][j]表示前i位对4,5,6取模后结果为j的情况数,发现这个对于每一位都是一样的,可以使用矩乘优化计算。但是我的DP一直是错的……到死也没de出来。

    后来发现我的计算是不对的,不应该对4,5,6分别计算,而应该对它们的lcm60取模,这样的话我们使用矩乘优化,之后取所有能整除4,5,6的数的结果即可。

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<queue>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 60;
    const int INF = 1000000009;
    const ll mod = 1e9+7;
    
    ll read()
    {
        ll ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    struct matrix
    {
        ll a[65][65];
        void init(int x)
        {
        memset(a,0,sizeof(a));
        rep(i,0,M-1) a[i][i] = x;
        }
        matrix operator * (const matrix &g) const
        {
        matrix p;
        p.init(0);
        rep(i,0,M-1)
        rep(j,0,M-1)
        rep(k,0,M-1) p.a[i][j] += a[i][k] * g.a[k][j],p.a[i][j] %= mod;
        return p;
        }
        matrix operator *= (const matrix &g)
        {
        return *this = *this * g;
        }
        matrix operator ^ (ll g)
        {
        matrix p,q = *this;
        p.init(1);
        while(g)
        {
            if(g & 1) p *= q;
            q *= q;
            g >>= 1;
        }
        return p;
        }
    }f,g;
    
    ll l,r,k,ans;
    
    int main()
    {
        l = read(),r = read(),k = read();
        f.init(0);
        rep(i,0,M-1)
        {
        rep(j,0,M-1) f.a[j][i] = k / M % mod;
        rep(j,0,k%M-1) f.a[(i+j) % M][i]++,f.a[(i+j) % M][i] %= mod;
        }
        g = f ^ r;
        rep(i,0,M-1) if(i % 4 == 0 || i % 5 == 0 || i % 6 == 0) ans += g.a[i][0],ans %= mod;
        g = f ^ (l - 1);
        rep(i,0,M-1) if(i % 4 == 0 || i % 5 == 0 || i % 6 == 0) ans += (mod - g.a[i][0]),ans %= mod;
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    IDT 信息设计工具使用
    子查询
    分组函数
    多表查询
    单行函数
    基本的sql-select语句
    final关键字的使用
    非静态代码块(非static初始化块)&静态代码块(static初始化块)
    单例模式的饿汉式实现
    static关键字的应用
  • 原文地址:https://www.cnblogs.com/captain1/p/9866144.html
Copyright © 2011-2022 走看看