zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 80 (Rated for Div. 2)

    B,B:a*b+a+b=a*10b的位数+b。化简得知b+1=10b的位数。所以只有9,99,999……这样是可行的。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=4e5+10;
    typedef long long ll;
    ll n,m,ans;
    char l,r;
    char s[maxn];
    int a[maxn];
    int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int work(int x)
    {
        int ans=0;
        while(x){
            ans++;
            x/=10;
        }
        return ans;
    }
    int run(int x)
    {
        int vis=0;
        while(x){
            if(x%10!=9) vis=1;
            x/=10;
        }
        if(vis==1) return 1;
        else return 0;
    }
    int main()
    {
        int T;
        T=read();
        while(T--){
            n=read(),m=read();
            ll res=work(m);
            if(run(m)) res--;
            ll k=res*n;
            printf("%lld
    ",k);
        }
    }
    

    C

    给出n,m,表示你可以用1到n的元素组装出m个元素构成的字符串,如m=4,a=【1,1,1,3】 

    现在给出要求,要求a,b两个数组,a数组不能下降,b数组不能上升,然后a的对应位置元素要小于等于b。

    题解:

    我们将b数组放过来看,就和a一样是不能下降,也就和a一样了,也就是2m长度的不下降的序列有多少个,直接dp

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e3+10;
    const int P=1000000007;
    
    ll DP[maxn][maxn];
    
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)DP[1][i]=1;
        for(int i=2;i<=2*m;++i){
            for(int j=1;j<=n;++j){
                for(int k=1;k<=j;++k){
                    DP[i][j]=(DP[i][j]+DP[i-1][k])%P;
                }
            }
        }
        ll ans=0;
        for(int i=1;i<=n;++i){
            ans=(ans+DP[m][i])%P;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    

      

    D

    给出n个数组每个数组有m个元素(注意m很小),你每次可以选择任一两个数组,ai和aj,然后组成新数组,新数组的每个元素都是从对应的位置的连个数组中挑选最大的。

    问求所有组装方法中,这个新数组的最小元素是最大化的。

    题解:

    首先我们可以用二分方法来二分出这个值是多少,那二分的判断机制是什么?

    就是判断当前这个值(因为这个值是新数组元素最小的,所以其他元素就得大于等于它)

    同时我们发现这个m很小,故我们可以用状态压缩来表示状态。

    具体实现方式:

    我们利用状态压缩来表示a数组中每个元素是否大于x,如果大于等于,该位置就是1

    例如a(1 2 3 4 0)x=2,那么就算01110.

    然后记录当前状态是第几行得到的(多个相同状态也无所谓,随着x的提高也就是二分,我们会选出最优的那个的)。

    然后接下来开始匹配,首先是i|j==lim,也就是表明每个位置都是1,每个位置都有元素,然后判断这两个状态是否有数组提供。

    #include<stdio.h>
    #define ri register int
    #define il inline
    const int M=300005;
    const int N=12;
    int p[N],id[M],a[M][N],n,m,o1,o2,lim;
    bool ck(const int&x){
        ri i,j,res;
        for(i=0;i<=lim;++i) id[i]=0;//清空所有状态
        for(i=1;i<=n;++i){
            res=0;
            for(j=1;j<=m;++j)
                if(a[i][j]>=x) res|=p[j];//满足条件的状态压缩起来
            id[res]=i;//记录这个状态是抽出第行得到的
        }
        for(i=0;i<=lim;++i)//枚举i,j两个状态进行检查,是否可以抽出id[i]和id[j]以得到答案
            for(j=i;j<=lim;++j)//j从i枚举,以免重复计算
                if((i|j)==lim&&id[i]&&id[j])
                    return o1=id[i],o2=id[j],1;
        return 0;
    }
    il void ms(){//MidSearch 即二分现在最大最小的b
        int l=0,r=1e9,mid;
        while(l<=r)
            mid=l+r>>1,ck(mid)?l=mid+1:r=mid-1;//满足条件,说明还可能存在较大解
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(ri i=1,j;i<=n;++i)
            for(j=1;j<=m;++j) scanf("%d",&a[i][j]);
        lim=(1<<m)-1;
        for(ri i=1;i<=m;++i) p[i]=1<<i-1;//常数优化
        ms(),printf("%d %d
    ",o1,o2);//输出任意一组满足条件的解即可
        return 0;
    }
    

      

  • 相关阅读:
    js变量类型
    js词法分析
    ORACLE 查找字段在哪些表里存在
    主外键约束的关闭和启用
    pl/sql developer 编码格式设置(转)
    WIN7 Net Configuration Assistant打不开
    Kettle 连接失败 Oracle 数据库报 ora-12505 的解决方法(转)
    正则表达式30分钟入门教程(转)
    设置程序的多个入口,进行动态的显示
    应用多入口配置
  • 原文地址:https://www.cnblogs.com/hgangang/p/12202461.html
Copyright © 2011-2022 走看看