AtCoder Regular Contest 116(A-D)

A、Odd vs Even

  • editorial

    已知对于给定数字(n),他的因子可以表示成(prodlimits_{i=1}^{m}p_i^{cnt_i}),其中(p_i)是n的素因子,(cnt_i in [0,a_i]), (a_i)是满足([n mod p_i^{a_i} = 0])这个条件的最大值。

    故知若(2^{a_i})中的(a_i)大于1时,偶因子多于奇因子个数;两者相等时,偶因子等于奇因子个数;否则,偶因子少于奇因子个数。

  • code

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t--)
        {
            ll n;
            scanf("%lld", &n);
            if(n % 4 == 0)
                puts("Even");
            else if(n % 2 == 0 )
                puts("Same");
            else
                puts("Odd");
        }
        return 0;
    }
    

B、Products of Min-Max

  • editorial

    首先我们对该序列进行排序,发现就可以固定两端,中间是否选择,共有(2^{max(0,j-i+1)})中选择,故答案为

    [sumlimits_{i=1}^nsumlimits_{j=i}^na_i*a_j*2^{max(0,j-i-1)}=sumlimits_{i=1}^na_i*sumlimits_{j=i}^na_j*2^{max(0,j-i-1)} =sumlimits_{i=1}^na_i*sumlimits_{j=i+1}^na_j*2^{j-i-1}+sumlimits_{i=1}^na_i^2 ]

    观察式子发现

    (sumlimits_{j=i}a_j*2^{j-i}=2*sumlimits_{j=i+1}a_j*2^{j-i}+a_i)

    故我们从后往前计算。

  • code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int NMAX = 2e5 + 10;
    const int MOD = 998244353;
     
    int a[NMAX];
    int main()
    {
        int n;
        scanf("%d", &n);
        ll ans = 0, ant;
        for(int i = 1;i <= n;i++)   
        {
            scanf("%d", a + i);
            ans = (ans + 1ll*a[i]*a[i]%MOD)%MOD;
        }
        sort(a + 1, a + 1 + n);
        ant = a[n];
        for(int i = n-1;i >= 1;i--)
        {
            ans = (ans + ant*a[i]%MOD)%MOD;
            ant = (ant*2%MOD + a[i])%MOD;
        }
        printf("%lld
    ", ans);
        return 0;
    }
    

C、Multiple Sequences

  • editorial

    对于整数(m),连续的因子序列(因子序列中元素互不相等),最大长度为(lfloorlog_2m floor),故进行dp,(dp[i][j])表示最后一位数字,当前序列长度为(i)的可能情况。

    而对于原问题的序列我们可以通过我们的序列进行扩展,即将长度为(i)的序列扩展成长度为(n),即可以想象把长度为(n)的序列划分为(i)段,用插空法求出有((n-1,i-1))种方式,故答案为(sumlimits_{i=1}^{20}(n-1,i-1)*(sumlimits_{j=1}^mdp[i][j]))

  • code

    #include<bits/stdc++.h>
     
    using namespace std;
    const int NMAX = 2e5 + 10;
    const int MOD = 998244353;
    typedef long long ll;
     
    ll dp[20][NMAX], sum[20];
    ll f[NMAX],finv[NMAX];
    ll fast_pow(ll a,ll n)
    {
        ll ans = 1;
        while(n)
        {
            if(n&1) ans = (ans * a)%MOD;
            a = (a * a)%MOD;
            n >>= 1;
        }
        return ans;
    }
    ll C(ll n,ll m)
    {
    	return (n<0||m<0||n<m)?0:f[n]*(finv[m])%mod*finv[n-m]%mod;
    }
    void init()
    {
        f[0]=1;
        for(int i=1;i< NMAX;i++)
            f[i]=f[i-1]*i%mod;
        finv[NMAX-1] = fast_pow(f[NMAX-1],mod-2);
        for (int i=NMAX-1; i > 0; i--)
            finv[i-1]=finv[i]*i%mod;
    }	
    int main()
    {
        int n, m;
        init();
        scanf("%d%d", &n, &m);
        for(int i = 1;i <= m;i++)   dp[1][i] = 1;
        sum[1] = m%MOD;
        for(int j = 2;j < 20;j++)
        {
            for(int i = 1;i <= m;i++)
                for(int k = 2*i; k <= m;k += i)
                    dp[j][k] = (dp[j][k] + dp[j-1][i])%MOD;
            for(int i = 1;i <= m;i++)
                sum[j] = (sum[j] + dp[j][i])%MOD;
        }
        
        ll ans = 0;        
        for(int i = 1;i < 20;i++)
            ans = (ans + C(n-1, i-1)*sum[i]%MOD)%MOD;  
        printf("%lld
    ", ans);
        return 0;
    }
    

D、Wanna Win The Game

  • editorial
    官方题解
    (sum A_i)为偶数时,(Xor A_i)才可能存在情况数,对于所有的(A_i)二进制,固定位的(1)的个数必然为偶数。那我们从低位往高位开始,构造序列(A)
    定义(dp[i])(m=i)的答案,首先构造最后一位,即对于偶数(m),将(m)(1)放到(n)个位置(保证一个位置至多只有一个一),共有((n, m))中方案。用之前的方案数来更新当前的情况,即在原来的序列每个元素左移一位,然后选择(2j)(1),分别加到序列(A)中,故有转移方程如下:

[ dp[i*2+j] = 1ll*(dp[(i<<1)+j] + 1ll*dp[i]*C[n][j] mod MOD) mod MOD iff jequiv0pmod{2} ]

  • code

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MOD = 998244353;
    const int NMAX = 5e3 + 5;
    
    typedef long long ll;
    
    int C[NMAX][NMAX];
    int dp[NMAX];
    void init()
    {
        C[0][0] = 1;
        for(int i = 1;i < NMAX;i++)
        {
            C[i][0] = 1;
            for(int j = 1;j <= i;j++)
                C[i][j] = (C[i-1][j] + C[i-1][j-1])%MOD;
        }
    }
    
    int main()
    {
        init();
        int n, m;
        scanf("%d%d", &n, &m);
        for(int i = 2;i <= m;i += 2)
            dp[i] = C[n][i];
        for(int i = 1;i <= m;i++)
            for(int j = 0;(i<<1)+j <= m;j += 2)
                dp[i*2+j] = 1ll*(dp[(i<<1)+j] + 1ll*dp[i]*C[n][j]%MOD)%MOD;
        printf("%d
    ", dp[m]);
        return 0;
    }
    
原文地址:https://www.cnblogs.com/lemon-jade/p/14595311.html