• AtCoder Regular Contest 116 总结


    A

    判断奇偶因子谁多谁少

    容易发现如果质因数分解,有 n 个 2 和 m 个非 2 质因子

    则奇数因子有 $2^m$ 个 ,偶数因子有 $2^{n+m-1}$ 个(没有 2 时没有)

    可知当 n=0 时奇数多, n=1 时一样, n=2 时偶数多

    #include <iostream>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    int t;
    ll n;
    
    int main() {
        for (scanf("%d",&t);t;t--) {
            scanf("%lld",&n);
            if (n%2!=0) {printf("Odd
    ");continue;}
            n/=2;
            if (n%2!=0) {printf("Same
    ");continue;}
            else printf("Even
    ");
        }
    }
    View Code

    B

    求对于一个序列 A ,它的子序列 B 的 $sum_B max(B)*min(B)$

    将 A 排序,枚举左右端点为 l,r ,则当前答案为 $a[l]*a[r]*2^{r-l-1} (r>l)$ 再加上 $a[l]*a[r] (r=l)$

    考虑用后缀和维护 $a[r]*2^{r-1}$ 则枚举左端点 l 时答案为 $a[l]*s[r]*2^{-l} (r>l)$ 再加上 $a[l]*a[r] (r=l)$

    时间复杂度 O(n)

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const ll P=998244353;
    const int N=2e5+10;
    int n;
    ll a[N],_2[N],suf[N],ans;
    
    ll Pow(ll x,ll y) {ll ans=1;for (;y;y>>=1,x=x*x%P) if (y&1) ans=ans*x%P;return ans;}
    
    int main() {
        scanf("%d",&n);
        _2[0]=1;for (int i=1;i<=n;i++) scanf("%lld",&a[i]),_2[i]=(_2[i-1]<<1)%P;
        sort(a+1,a+n+1);
        for (int i=n;i;i--)    suf[i]=(suf[i+1]+a[i]*_2[i-1]%P)%P;
        for (int i=1;i<=n;i++)
            (ans+=a[i]*suf[i+1]%P*Pow(_2[i],P-2)%P+a[i]*a[i]%P)%=P;
        printf("%lld
    ",ans);
    }
    View Code

    C

    在一个序列中不同的数至多有 $log_2m$ 个

    则设 f[i][j] 表示第 i 个不同的数是 j , 从上一个 j 的因子里转移过来,复杂度是调和级数 O(nlnn)

    最后枚举有 i 个不同的数,在 n-1 个空隙里插 i-1 个板即可

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const ll P=998244353;
    const int N=2e5+10;
    int n,m,lg;
    ll fact[N],inv[N],f[21][N],ans;
    
    ll Pow(ll x,ll y) {ll ans=1;for (;y;y>>=1,x=x*x%P) if (y&1) ans=ans*x%P;return ans;}
    
    ll C(int n,int m) {return fact[n]*inv[n-m]%P*inv[m]%P;}
    
    int main() {
        scanf("%d%d",&n,&m);lg=log2(m);
        fact[0]=1;for (int i=1;i<N;i++) fact[i]=fact[i-1]*i%P;
        inv[N-1]=Pow(fact[N-1],P-2);for (int i=N-2;i>=0;i--) inv[i]=inv[i+1]*(i+1)%P;
        for (int i=1;i<=m;i++) f[0][i]=1;
        for (int i=1;i<=lg;i++)
            for (int j=1;j<=m;j++)
                for (int k=2;k*j<=m;k++) (f[i][j*k]+=f[i-1][j])%=P;
        for (int i=0;i<=min(lg,n-1);i++)
            for (int j=1;j<=m;j++) (ans+=f[i][j]*C(n-1,i))%=P;
        printf("%lld
    ",ans);
    }
    View Code

    D

    范围很小,做法很暴力

    从低位到高位,设 f[i][j] 表示做到第 i 位,前面 i-1 位满足相消为 0 的方案数

    O(mlogm)

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const ll P=998244353;
    const int N=5e3+10;
    int n,m,lg;
    ll fact[N],inv[N],f[15][N];
    
    ll Pow(ll x,ll y) {ll ans=1;for (;y;y>>=1,x=x*x%P) if (y&1) ans=ans*x%P;return ans;}
    
    ll C(int n,int m) {return fact[n]*inv[n-m]%P*inv[m]%P;}
    
    int main() {
        scanf("%d%d",&n,&m);lg=log2(m);
        if (m&1) return printf("0"),0;
        fact[0]=1;for (int i=1;i<=n;i++) fact[i]=fact[i-1]*i%P;
        inv[n]=Pow(fact[n],P-2);for (int i=n-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%P;
        f[0][0]=1;
        for (int i=0,k=1;i<=lg;i++,k<<=1)
            for (int j=0;j<=m;j++) {
                for (int l=2;j+k*l<=m&&l<=n;l+=2) (f[i+1][j+k*l]+=f[i][j]*C(n,l)%P)%=P;
                (f[i+1][j]+=f[i][j])%=P;
            }
        printf("%lld
    ",f[lg+1][m]);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    iOS 开发中的坑与相关技巧
    SDK 封装的相关看法
    线程问题---在iPad上会崩溃,在iPhone上不会崩溃
    添加新手引导页需要注意的几个小点
    iOS 七牛云上传并获取图片----【客户端】
    iOS 线程相关-----绝对de干货
    Vue.js 基础示例
    lib-flexible 结合 WKWebView 的样式错乱解决方法
    基于CommentCoreLibrary简单的弹幕实现
    页面上动态编译及执行java代码
  • 原文地址:https://www.cnblogs.com/mastervan/p/14594429.html
Copyright © 2020-2023  润新知