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
原文地址:https://www.cnblogs.com/captain1/p/9866144.html