• 2017 Multi-University Training Contest


    2017 Multi-University Training Contest - Team 4

    03  / hdu6069    数学,素数筛

    题意: d(n)表示 n 的因子个数,求 d(i^k),l<=i<=r 。

    tags: 算术基本定理拆开,然后素数筛过去。

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (ll i=a; i<=b; ++i)
    #define per(i,b,a) for (ll i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const ll N = 1000105, mod = 998244353;
    
    ll  l, r, k, ans[N], pri[N], num[N];
    int tot;
    bool  mark[N];
    void getprime()
    {
        for(int i=2; i<N; ++i) if(mark[i]==0) {
            pri[++tot]=i;
            for(int j=i+i; j<N; j+=i)  mark[j]=1;
        }
    }
    void Init()
    {
        for(int i=0; i<N; ++i) ans[i]=1;
        for(ll i=l; i<=r; ++i) num[i-l] = i;
    }
    int main()
    {
        getprime();
        int T;   scanf("%d", &T);
        while(T--)
        {
            scanf("%lld%lld%lld", &l, &r, &k);
            Init();
            for(int ca=1; ca<=tot && pri[ca]<=r; ++ca)
            {
                ll p=pri[ca], x=p;
                if(p<l)  x = (l+p-1)/p*p;
                for(ll x1=x; x1<=r; x1+=p)
                {
                    ll cnt1=0;
                    while(num[x1-l]%p==0) ++cnt1, num[x1-l]/=p;
                    ( ans[x1-l] *= (k*cnt1+1)%mod ) %= mod ;
                }
            }
            ll  ans1=0;
            for(ll i=l; i<=r; ++i) if(num[i-l] != 1) ( ans[i-l] *= k+1 ) %= mod;
            for(ll i=l; i<=r; ++i)  ( ans1 += ans[i-l] ) %= mod;
            printf("%lld
    ", (ans1+mod)%mod);
        }
    
        return 0;
    }
    View Code

    04 / hdu6070    最优比率,二分+线段树维护

    题意:给出n个的提交的题目的标号,求任意一个区间最小的AC率。

    tags: 这个 二分+线段树 很神奇,根本想不到。。

    官方题解:二分答案mid,检验是否存在一个区间满足size(l,r)/(r−l+1) ≤ mid,式子变化一下就是:size(l,r) + mid​*l​​ ≤ mid*(r+1) 。从左往右枚举每个位置作为r,当r变化为r+1时,对size的影响是一段区间加1,线段树维护区间最小值即可。时间复杂度O(n*logn*logw)。

    最关键的是想到这个式子变化为 size(l,r)+mid*l ,然后在线段树中维护 size(l,r)+mid*l 。 而从左往右枚举右端点 ,即利用线段树累加省去了枚举左端点的操作,和 CF 833B  有点像 。

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 60005;
    const double eps = 1e-6;
    
    int n, pre[N], now[N], a[N];
    double lazy[N<<4], tr[N<<4];
    void pushup(int ro)
    {
        tr[ro] = min(tr[ro<<1], tr[ro<<1|1]);
    }
    void build(int ro, int l, int r, double v)
    {
        lazy[ro] = 0, tr[ro] = v*l;
        if(l==r) return ;
        int mid = l+r>>1;
        build(ro<<1, l, mid, v);
        build(ro<<1|1, mid+1, r, v);
        pushup(ro);
    }
    void tag(int ro, double v)
    {
        lazy[ro] += v, tr[ro] += v;
    }
    void pushdown(int ro)
    {
        if(lazy[ro]>eps)
        {
            tag(ro<<1, lazy[ro]);
            tag(ro<<1|1, lazy[ro]);
            lazy[ro] = 0;
        }
    }
    void update(int ro, int l, int r, int ql, int qr, double v)
    {
        if(ql<=l && r<=qr) {
            tag(ro, v);
            return ;
        }
        pushdown(ro);
        int mid = l+r>>1;
        if(ql<=mid) update(ro<<1, l, mid, ql, qr, v);
        if(mid<qr) update(ro<<1|1, mid+1, r, ql, qr, v);
        pushup(ro);
    }
    double query(int ro, int l, int r, int ql, int qr)
    {
        if(ql<=l && r<=qr) return tr[ro];
        pushdown(ro);
        int mid = l+r>>1;
        double mi = 1e18;
        if(ql<=mid) mi = min(mi, query(ro<<1, l, mid, ql, qr));
        if(mid<qr) mi = min(mi, query(ro<<1|1, mid+1, r, ql, qr));
        return mi;
    }
    bool check(double x)
    {
        build(1, 1, n, x);
        rep(i,1,n)
        {
            update(1, 1, n, pre[i]+1, i, 1);
            if(query(1, 1, n, 1, i) <= x*(i+1)) return true;
        }
        return false;
    }
    int main()
    {
        int T;  scanf("%d", &T);
        while(T--)
        {
            mes(now, 0);
            scanf("%d", &n);
            rep(i,1,n)
            {
                scanf("%d", &a[i]);
                pre[i] = now[a[i]], now[a[i]] = i;
            }
            double l=0, r=1.0, mid;
            //rep(ca,0,25)
            while(fabs(r-l)>eps)
            {
                mid = (l+r)/2;
                if(check(mid)) r=mid;
                else l=mid;
            }
            printf("%.5f
    ", mid);
        }
    
        return 0;
    }
    View Code

     12 / hdu6078   dp+树状数组优化

    题意:定义了''wavel''序列为:a1<a2>a3<a4>a5<a6... 求f()和g()的方案数。

    tags:看不懂题解怎么写的,但树状数组优化卡过去了。。

    dp[i][j][1/0] 表示a[i]与b[j]相同时,a[i] 作为最后一个波谷/波峰的方案数。

    转移:dp[i][j][1] = max(dp[x][y][0]) ,  (x<i, y<j, a[x]>a[i], a[x]==b[y]) ;    dp[i][j][0] = max(dp[x][y][1]) ,  (x<i, y<j, a[x]<a[i], a[x]==b[y]) 。

    所以对于 dp[i][j][1],只要找比 a[i] 先出现且比它大的 a[x] 有多少个,进行递推即可。 dp[i][j][0] 同理。

    //  4
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 2005, mod = 998244353;
    
    int n, m, a[N], b[N], mx;
    ll  dp[N][N][2], bit[N][2];
    void Add(int x, ll v, int flag) {
        for(; x<=mx; x+=x&-x) ( bit[x][flag] += v ) %= mod;
    }
    ll  Sum(int x, int flag) {
        ll ans=0; for(; x>0; x-=x&-x) ans = (ans+bit[x][flag])%mod; return ans;
    }
    int main()
    {
        int T;  scanf("%d", &T);
        while(T--)
        {
            scanf("%d%d", &n, &m);
            mx = 0;
            rep(i,1,n) scanf("%d", &a[i]), mx = max(mx, a[i]);
            rep(i,1,m) scanf("%d", &b[i]), mx = max(mx, b[i]);
            mes(dp, 0);
            ll  ans = 0;
            rep(i,1,n)
            {
                rep(j,1,m) {
                    ( dp[i][j][0] += dp[i-1][j][0] ) %= mod;
                    ( dp[i][j][1] += dp[i-1][j][1] ) %= mod;
                }
                rep(j,0,mx)
                    bit[j][0] = bit[j][1] = 0;
                rep(j,1,m)
                {
                    if(a[i]==b[j])
                    {
                        ll  tmp1 = Sum(b[j]-1, 1), tmp2 = Sum(mx, 0)-Sum(b[j], 0);
                        ( dp[i][j][0] += tmp1 ) %= mod;
                        ( dp[i][j][1] += tmp2+1 ) %= mod;
                        ( ans += (tmp1+tmp2+1)%mod ) %= mod;
                    }
                    Add(b[j], dp[i-1][j][0], 0);
                    Add(b[j], dp[i-1][j][1], 1);
                }
            }
            printf("%lld
    ", (ans+mod)%mod);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    [bzoj3999] [TJOI2015]旅游
    [bzoj3143] [HNOI2013]游走
    [bzoj3140] [Hnoi2013]消毒
    [bzoj3142] [HNOI2013]数列
    [bzoj4860] [BeiJing2017]树的难题
    [bzoj2599] [IOI2011]Race
    [bzoj1558] [JSOI2009]等差数列
    [bzoj3626] [LNOI2014]LCA
    [bzoj4011] [HNOI2015]落忆枫音
    JQuery
  • 原文地址:https://www.cnblogs.com/sbfhy/p/7281448.html
Copyright © 2020-2023  润新知