zoukankan      html  css  js  c++  java
  • AtCoder Regular Contest 122 A~D题解

    本场链接:Tokio Marine & Nichido Fire Insurance Programming Contest 2021(AtCoder Regular Contest 122)

    A - Many Formulae

    容易想到按当前做到哪一个数作为划分依据进行dp,进一步可以发现放置的符号也是有关的:

    • 状态:(f[i][j])表示做完前(i)个元素,(i)元素之前的符号是(j = 0)+反之为-.
    • 入口:(f[1][0] = 1)
    • 转移:可以发现填充符号的时候可能会有多个符合这个局面的和存在,额外记录一个状态表示个数:(c[i][j])(f[i][j]),则(f[i][0] = (f[i - 1][0] + f[i - 1][1])*c[i][0],f[i][1] = f[i - 1][0] * c[i][1]).(c[i][0] = c[i - 1][0] + c[i - 1][1],c[i][1] = c[i - 1][0]).
    • 出口:(f[n][0] + f[n][1]).
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)
    #define forr(i,x,n) for(int i = n;i >= x;--i)
    #define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
    #define int ll
    const int N = 1e5+7,MOD = 1e9+7;
    int a[N],f[N][2],c[N][2];
    
    signed main()
    {
        int n;scanf("%lld",&n);
        forn(i,1,n) scanf("%lld",&a[i]);
        f[1][0] = a[1];
        c[2][0] = 1;c[2][1] = 1;
        forn(i,3,n) c[i][0] = (c[i - 1][0] + c[i - 1][1]) % MOD,c[i][1] = c[i - 1][0];
        forn(i,2,n)
        {
            f[i][0] = (1ll * f[i - 1][0] + f[i - 1][1] + 1ll * c[i][0] * a[i] % MOD) % MOD;
            f[i][1] = ((f[i - 1][0] - 1ll * c[i][1] * a[i] % MOD) % MOD + MOD) % MOD;
        }
        printf("%lld
    ",((f[n][0] + f[n][1]) % MOD + MOD) % MOD);
        return 0;
    }   
    
    

    B - Insurance

    因为表达式和(min(a_i,2x))有关,考虑按段枚举(x)的取值:([0,a_1/2],[a_1/2,a_2/2]...),将答案表达出来再根据单调性求值即可.特别的,当(xin[a_n/2,+infin])这个区间的时候取(x=a_n/2)最小,可以作为初值.

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)
    #define forr(i,x,n) for(int i = n;i >= x;--i)
    #define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
    
    const int N = 1e5+7;
    int a[N];
    ll sum[N];
    
    int main()
    {
        int n;scanf("%d",&n);
        forn(i,1,n) scanf("%d",&a[i]);
        sort(a + 1,a + n + 1);
        forn(i,1,n) sum[i] = sum[i - 1] + a[i];
        double res = a[n] / 2.0;
        forn(i,0,n - 1)
        {
            double x;
            if(2 * i <= n)  x = a[i + 1] / 2.0;
            else x = a[i] / 2.0;
            res = min(res,(sum[n] - sum[i]) * 1.0 / n + (2 * i - n) * x / n);
        }
    
        printf("%.18lf
    ",res);
        return 0;
    }   
    
    

    C - Calculator

    这种构造题肯定有某种很特别的构造方式,(1)(2)操作都非常平常,然后可以非常神棍的这样发现:(x=1,y=0)如果交替执行(3,4,3,4....),(x,y)一定各是某个斐波那契数:考虑把(n)表达成某些(fib(x))的和.假设一开始整个操作序列仅限于(3,4,3,4...),如果在一开始给一个(x=1)的操作的话,那么由于超过86步之后就会超过(10^{18})所以这样交替操作的步数不会超过(86)左右.进一步的,可以发现如果在第(i)步插入(1)/(2)操作,就会让(x)的结果增加(fib(k-i)),其中(k)是交替的操作总步数.因为偶数步结束的时候是由(y)增加(x),所以在偶数步插入(1)操作;反过来插入(2)操作.

    具体来说,首先找一个最大的(t),满足(f(t) leq n).一开始的操作序列是交替执行(3,4...)一共(t)个.之后从大到小枚举是否可以插入(fib(i)),如果可以就直接放入并更新操作,如此构造即可.

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)
    #define forr(i,x,n) for(int i = n;i >= x;--i)
    #define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
    
    const int N = 105;
    ll f[N];
    
    int main()
    {
        ll n;scanf("%lld",&n);
        f[0] = 1;f[1] = 1;
        int t = 1;
        while(f[t - 1] + f[t] <= n) ++t,f[t] = f[t - 1] + f[t - 2];
        ll cur = n,res = t;
        forr(i,1,t) if(cur >= f[i])   cur -= f[i],++res;
        printf("%d
    ",res);
        forr(i,1,t)
        {
            if(n >= f[i])   n -= f[i],printf("%d
    ",(i&1) + 1);
            printf("%d
    ",((i - 1) & 1) + 3);
        }
        return 0;
    }   
    
    

    D - XOR Game

    考虑最终的答案每一位的取值:要让这个值比较小是比较顺的想法.

    从高到低考虑每一位:如果(2n)个元素在这一位取(1)和取(0)的个数都是偶数,那么显然无论先手选择哪个元素,后手都可以镜像操作使这一位变成(0),为了保证之后不在这一位产生(1),将所有这一位是(0)的元素划分成一组,其他另成一组,往下递归继续做;如果是奇数,那么必须要从(1)(0)两组元素中取一对出来,剩下的所有元素这一位产生的结果都会是(0),而且往后不可能有一个结果比取出来的一对数的结果更大,所以一旦出现了这样取一对出来的情况,他就是序列后缀能产生的最大值,因为不可能再有一对元素在这一位产生(1).所以取两个集合中异或值最小的一对元素即是这个后缀的答案.

    如此可以先对整个({a})排序,这样就可以快速找到某位取(1)的分界线.之后执行一个dfs框架,每次划分组往下递归,找到不同的就求出答案返回.

    对于两个集合各取一个元素求异或最小值的子问题是Trie基本操作,难度和本题差距过大就不展开了.

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)
    #define forr(i,x,n) for(int i = n;i >= x;--i)
    #define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
    
    const int N = 4e5+7,M = 32;
    int tr[N * M][2],cnt[N * M],a[N],idx,n;
    
    void insert(int x,int v)
    {
        int p = 0;
        forr(i,0,30)
        {
            int k = x >> i & 1;
            if(!tr[p][k])   tr[p][k] = ++idx;
            cnt[tr[p][k]] += v;
            p = tr[p][k];
        }
    }
    
    int query(int x)
    {
        int p = 0,res = 0;
        forr(i,0,30)
        {
            int k = x >> i & 1;
            if(tr[p][k] && cnt[tr[p][k]])   
            {
                p = tr[p][k];
                if(k)   res |= 1 << i;
            }
            else
            {
                p = tr[p][k ^ 1];
                if(k ^ 1)   res |= 1 << i;
            }
        }
        return res ^ x;
    }
    
    int dfs(int L,int R,int v,int dep)
    {
        if(dep < 0 || L > R)   return 0;
        int p = lower_bound(a + 1,a + n + 1,v | (1 << dep)) - a;
        if((p - L) % 2 == 0)    return max(dfs(L,p - 1,v,dep - 1),dfs(p,R,v | (1 << dep),dep - 1));
        int res = 2e9;
        forn(i,0,idx)   tr[i][0] = tr[i][1] = 0;idx = 0;
        forn(i,L,p - 1) insert(a[i],1);
        forn(i,p,R) res = min(res,query(a[i]));
        return res;
    }
    
    int main()
    {
        scanf("%d",&n);n *= 2;
        forn(i,1,n) scanf("%d",&a[i]);
        sort(a + 1,a + n + 1);
        printf("%d
    ",dfs(1,n,0,30));
        return 0;
    }   
    
    
  • 相关阅读:
    稳扎稳打Silverlight(47) 4.0UI之操作剪切板, 隐式样式, CompositeTransform, 拖放外部文件到程序中
    返璞归真 asp.net mvc (9) asp.net mvc 3.0 新特性之 View(Razor)
    返璞归真 asp.net mvc (6) asp.net mvc 2.0 新特性
    稳扎稳打Silverlight(48) 4.0其它之打印, 动态绑定, 增强的导航系统, 杂七杂八
    精进不休 .NET 4.0 (9) ADO.NET Entity Framework 4.1 之 Code First
    稳扎稳打Silverlight(42) 4.0控件之Viewbox, RichTextBox
    稳扎稳打Silverlight(53) 4.0通信之对WCF NetTcpBinding的支持, 在Socket通信中通过HTTP检索策略文件, HTTP请求中的ClientHttp和BrowserHttp
    稳扎稳打 Silverlight 4.0 系列文章索引
    稳扎稳打Silverlight(54) 4.0通信之对UDP协议的支持: 通过 UdpAnySourceMulticastClient 实现 ASM(Any Source Multicast),即“任意源多播”
    返璞归真 asp.net mvc (8) asp.net mvc 3.0 新特性之 Model
  • 原文地址:https://www.cnblogs.com/HotPants/p/14881114.html
Copyright © 2011-2022 走看看