Codeforces Round #157(完整)

来源:互联网 发布:ttl数据查看 编辑:程序博客网 时间:2024/06/02 09:15

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 

259A:每一行,wbwbwbwb,bwbwbwbw这两种情况是合法的


259B:SB了半天,题目只说了对角线是未知的,随意瞎搞吧,不知道什么好办法 


258A:被cha一次,注意全为1的情况,就是从高位判断,去掉第一个0,如果全为1,则随便去掉一位


258B:数位DP+DFS

数位DP处理出1---n含有i个lucky number的数有多少个

然后DFS每一个候选者选的种类,直接计数

一直不敢写,对于数位DP,没有把握,不过还好最后过了

LL dp[15][15];void DP(){    mem(dp,0);    dp[0][0]=1;    for(int i=0;i<10;i++){        for(int j=0;j<=i;j++){            if(dp[i][j]==0) continue;            dp[i+1][j+1]+=dp[i][j]*2;            dp[i+1][j]+=dp[i][j]*8;        }    }}int slove(int n,int m){    int bit[20],len=0;    while(n){        bit[len++]=n%10;        n/=10;    }    int cnt=0,tot=0;    for(int i=len-1;i>=0;i--){        for(int j=0;j<bit[i];j++){            if(j==4||j==7){                if(tot!=m)                     cnt+=dp[i][m-tot-1];            }            else cnt+=dp[i][m-tot];        }        if(bit[i]==4||bit[i]==7) tot++;        if(tot>m) break;    }    if(tot==m) cnt++;    if(m==0) cnt--;    return cnt;}int n;int cnt[10],t[10];LL ans=0;void dfs(int idx,int now,int limit,LL ret){    if(idx==6){        ans=(ans+ret)%MOD;        return ;    }    for(int i=0;i<10;i++){        if(i+now>=limit) break;        if(t[i]==0) continue;        t[i]--;        dfs(idx+1,now+i,limit,ret*(t[i]+1)%MOD);        t[i]++;    }}int main(){    DP();    while(scanf("%d",&n)!=EOF){        for(int i=0;i<10;i++){            cnt[i]=slove(n,i);        }        ans=0;        for(int i=1;i<10;i++){            if(cnt[i]==0) continue;            memcpy(t,cnt,sizeof(cnt));            t[i]--;            dfs(0,0,i,cnt[i]%MOD);        }        printf("%I64d\n",ans);    }    return 0;}

258C:枚举lcm,然后找出所有的因子,假设约数个数为m

第一步先处理,肯定至少有一个数要取lcm,那么至少有一个数取lcm,便是所有>=lcm的数,都有m种可能,这样肯定包括没有取到lcm的情况,只要减掉所有数都取<lcm,即m-1种可能的

然后枚举其它因子

int n;int a[N],c[N];LL PowMod(LL a,LL b){    LL ret=1;    while(b){        if(b&1)            ret=((LL)ret*a)%MOD;        a=((LL)a*a)%MOD;        b>>=1;    }    return ret;}int main(){    while(scanf("%d",&n)!=EOF){        int limit=0;        mem(c,0);        for(int i=0;i<n;i++){            scanf("%d",&a[i]);            c[a[i]]++;            limit=max(limit,a[i]);        }        for(int i=N-2;i>=1;i--)             c[i]+=c[i+1];        LL ans=1;        vector<int>v;        for(int i=2;i<=limit;i++){            v.clear();            for(int j=1;j*j<=i;j++){                if(i%j==0){                    v.pb(j);                    if(j*j!=i)                        v.pb(i/j);                }            }            sort(v.begin(),v.end());            int m=v.size();            LL sum=((PowMod((LL)m,(LL)c[v[m-1]])-PowMod((LL)m-1,(LL)c[v[m-1]]))%MOD+MOD)%MOD;            for(int j=0;j<m-1;j++){                sum=(sum*PowMod((LL)j+1,(LL)c[v[j]]-c[v[j+1]]))%MOD;                if(sum<0) test;            }            ans=(ans+sum)%MOD;        }        printf("%I64d\n",ans);    }    return 0;}


258 D:概率DP

p[i][j]表示a[i]>a[j]的概率

那么初始可以得到

对于某一次操作,需要交换a[u],a[v]

那么可以交换,也可能交换,所以p[u][v]=p[v][u]=0.5。因为交换或者不交换,要么是逆序对,要么不是

那么之后枚举所有的i,i!=x&&i!=y

那么以p[u][i]为例,那么a[u]与a[i]的关系,如果a[u]和a[v]不交换,那么p[u][i]不变,这样的可能为p[u][i]*0.5

如果交换的话,则原来的v变为了u,则p[v][i]*0.5

所以p[u][i]=p[u][i]*0.5+p[v][i]*0.5;

最后叠加就是期望



258E:http://blog.csdn.net/acm_cxlove/article/details/8395747