Codeforces Round #259 (Div. 2) A/B/C/D

來源:互聯網
上載者:User

標籤:狀壓dp 輸出路徑 機率期望

A Little Pony and Crystal Mine


題意:給一個奇數n,列印菱形圖案,整個圖形佔n*n格。

例如--->輸入3,則列印圖案如下

*D*DDD*D*


演算法:

由中間那行為n個D,以t = n/2為界先打上半邊,每一行由D隔開的*的個數為離中間行的距離。

D的個數為n-當前行離中間行的距離*2。

下半邊同理。


#include<cstdio>#include<iostream>#include<cstring>using namespace std;int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        int h = n/2;        for(int i=1;i<=h;i++)        {            for(int j=0;j<h+1-i;j++)                putchar('*');            for(int k=0;k<n-(h+1-i)*2;k++)                putchar('D');            for(int j=0;j<h+1-i;j++)                putchar('*');            puts("");        }        for(int i=h+1;i<=n;i++)        {            for(int j=0;j< i-h-1;j++)                putchar('*');            for(int k=0;k<n-(i-h-1)*2;k++)                putchar('D');            for(int j=0;j< i-h-1;j++)                putchar('*');            puts("");        }    }    return 0;}

B. Little Pony and Sort by Shift
題意:給你一個n個數組成的序列,每次只能把最後一個數移動到最前面,問是否能通過若干次這種移動使得序列變為非遞減的序列,如果不能輸出-1,否則輸出至少需要幾次這樣的操作。
演算法:經觀察能通過操作變為非遞減的序列的特點是:只有一處兩個相鄰的數是遞減的,以這兩個數中間切斷,兩邊的序列都應該是遞增的。所以先找到這個突然遞減的點,然後掃描後一段(因為前一段在找分界線時已經間接判斷是遞增的了)如果又出現第二處突然遞減的點,則輸出-1。否則輸出後面一段的個數。
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#define maxn 100010using namespace std;int a[maxn];int main(){    int n,flag,t;    while(scanf("%d",&n)!=EOF)    {        for(int i=0;i<n;i++)            scanf("%d",&a[i]);        flag = 0,t = -1;        for(int i=0;i<n-1;i++)        {            if(a[i+1]<a[i])            {                t = i;                break;            }        }        if(t==-1)        {            printf("0\n");            continue;        }        for(int i=t+1;i<n-1;i++)        {            if(a[i+1]<a[i])            {                flag = 1;                break;            }        }        if(flag || a[0]<a[n-1])        {            printf("-1\n");            continue;        }        else printf("%d\n",n-t-1);    }    return 0;}


C. Little Pony and Expected Maximum

題意:投擲一個m面的骰子n次,問得到的最大數的期望。
演算法:最大數為i,則得到i的機率為  ( i/m)^n -  (i-1/m)^n  即用(i/m)^n減去最大數為i-1的機率。
#include<cstdio>#include<iostream>#include<cstring>#include<cmath>#define maxm 100010using namespace std;double p[maxm],ans[maxm];int main(){    int m,n;    while(scanf("%d%d",&m,&n)!=EOF)    {        double res = 0;        ans[0] = 0;        for(int i=1;i<=m;i++)        {            ans[i] = pow((i*1.0)/m,n);            p[i] = ans[i]-ans[i-1];        }        for(int i=1;i<=m;i++)            res += p[i]*i;        printf("%lf\n",res);    }    return 0;}


D. Little Pony and Harmony Chest
題意:給一個序列a,要構造一個序列b,使得sum(|bi-ai|)最小且任意兩個bi的最大公用因子為1。
開始想到的是由於最大公用因子為1,所以b序列應該全為素數組成。每次找最鄰近的素數。但這樣是不對的。如果同一個素數出現兩次,則他們的最大公用因子是它們本身。
演算法:1、ai的最大值為30,最小值為1,所以不管怎樣bi取1是能滿足最大公用因子為1的限制的,現在要尋找比取1使sum(|bi-ai|)更小的解。那麼bi最大不會超過59 (30-1 = 29 ,30+29 = 59) 。
2、由於任何一個數都能由若干個素數因子表示而成。要想最大的公用因子為1,則素數因子的狀態不能重複取。而60以內的素數只有17個,這時我們狀態壓縮,用每一位來表示第幾個素數因子。把1-59的素數因子用狀態記錄下來。
3、dp[i][j]表示前i個數得到j狀態的最小的sum(|bi-ai|)值。
當前一個狀態dp[i-1][k]的k&val[x]=0時,dp[i][k] = max(dp[i][k],dp[i-1][k^val[x]]+abs(a[i]-x)),val[x]表示x的素數因子狀態。
用ans[i][j]選項組的轉移,這樣就好輸出b序列。這裡利用了^運算的可逆性。
#include<cstdio>#include<iostream>#include<cstring>#define maxn 60#define INF 0x3f3f3f3f#include<cmath>using namespace std;bool isp[maxn];int pri[maxn],c,a[110],b[110],val[maxn],dp[110][(1<<18)],ans[110][(1<<18)];void init(){    memset(isp,0,sizeof(isp));    c = 0;    for(int i=2;i<maxn;i++)    {        if(!isp[i])        {            pri[c++] = i;            for(int j=i*2;j<maxn;j+=i)                isp[j] = true;        }    }}int main(){    int n;    init();    while(scanf("%d",&n)!=EOF)    {        memset(val,0,sizeof(val));        for(int i=1;i<=n;i++)            scanf("%d",&a[i]);        for(int i=1;i<60;i++)        {            for(int j=0;j<c;j++)            {                if(i%pri[j]==0)                    val[i] = (val[i]|(1<<j));            }        }        for(int i=0;i<=n;i++)        {            for(int j=0;j<(1<<c);j++)                dp[i][j] = INF;        }        for(int i=0;i<(1<<c);i++)            dp[0][i] = 0;        for(int i=1;i<=n;i++)        {            for(int j=0;j<(1<<c);j++)            {                for(int k=1;k<60;k++)                {                    if((j&val[k])==0)                    {                        int tmp = dp[i-1][j^val[k]]+fabs(a[i]-k);                        if(tmp<dp[i][j])                        {                            dp[i][j] = tmp;                            ans[i][j] = k;                        }                    }                }            }        }        int res = INF,state,x=0;        for(int i=0;i<(1<<c);i++)        {            if(dp[n][i]<res)            {                res = dp[n][i];                state = i;            }        }        for(int i=n;i>=1;i--)        {            b[x++] = ans[i][state];            int t = ans[i][state];            state = state^val[t];        }        for(int i=x-1;i>0;i--)            printf("%d ",b[i]);        printf("%d\n",b[0]);    }    return 0;}









聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.