2014多校訓練九(HDU 4960 HDU 4961 HDU 4965 HDU 4968 HDU 4969 HDU 4970),hdu4961

來源:互聯網
上載者:User

2014多校訓練九(HDU 4960 HDU 4961 HDU 4965 HDU 4968 HDU 4969 HDU 4970),hdu4961

HDU 4960 Another OCD Patient

題意:給你一串數字  相鄰x個數字合并成一個數字(相加)有一定代價  問  最少花費多少使得串變成迴文串

思路:

讀完題感覺像dp  資料範圍也像  就開始想怎麼表示狀態  最簡單的應該想到dp[i][j]表示i到j區間變成迴文串的最小花費  狀態想好了想做法  考慮將串分成AAAABBBBBBBCCC三段  即所有A合成一個數字  C也是  而且A和C相等  那麼B串就變成了子問題  但是A和C是不是都要枚舉呢?  這個串所有元素都是正的  那麼也就是對於一種A只能對應一種C  所以這個枚舉複雜度是O(n)的  而且每次做子問題都會至少去掉首尾2個元素  那麼複雜度也就是n^2層級

代碼:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 5010#define inf 2000000000typedef __int64 LL;int n,amt;int cost[N],dp[N][N];LL sum[N];int dfs(int l,int r){    if(l>=r) return 0;    if(dp[l][r]!=inf) return dp[l][r];    int i,j;    LL suml,sumr;    dp[l][r]=cost[r-l+1];    for(i=l,j=r;i<j;)    {        suml=sum[i]-sum[l-1];        sumr=sum[r]-sum[j-1];        if(suml==sumr)        {            dp[l][r]=min(dp[l][r],dfs(i+1,j-1)+cost[i-l+1]+cost[r-j+1]);            i++;            j--;        }        else if(suml>sumr) j--;        else i++;    }}int main(){    int i,j;    while(~scanf("%d",&n))    {        if(!n) break;        for(i=1;i<=n;i++)        {            scanf("%I64d",&sum[i]);            sum[i]+=sum[i-1];        }        for(i=1;i<=n;i++) scanf("%d",&cost[i]);        for(i=1;i<=n;i++)        {            for(j=1;j<=n;j++) dp[i][j]=inf;        }        dfs(1,n);        printf("%d\n",dp[1][n]);    }    return 0;}
HDU 4961 Boring Sum

題意:略

思路:

隊友做的  他一眼就看出來了…- -b  膜拜豬神!  做法就是正反掃兩邊  對於每個數  維護它的所有約數  這樣b和c數組相當於已知了  最後掃一遍求和

代碼:


#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>#include <vector>using namespace std;typedef __int64 ll;const ll mod = 1000000009;const double eps = 1e-9;const double pi = acos(-1.0);const int M=100005;int n,m;vector<int > F[M];void init(){    int i,j;    for(i=1;i<M;i++)        for(j=i;j<M;j+=i)            F[j].push_back(i);}int dpa[M],dpb[M];int ansa[M],ansb[M];int a[M];int main(){    init();    int i,j;    int T,ca=0;    while(~scanf("%d",&n))    {        memset(dpa,0,sizeof(dpa));        memset(dpb,0,sizeof(dpb));        if(!n)            break;        for(i=1;i<=n;i++)            scanf("%d",&a[i]);        for(i=1;i<=n;i++)        {            if(!dpa[a[i]])                ansa[i]=i;            else                ansa[i]=dpa[a[i]];            for(j=0;j<F[a[i]].size();j++)            {                int now=F[a[i]][j];                dpa[now]=i;            }        }        for(i=n;i>=1;i--)        {            if(!dpb[a[i]])                ansb[i]=i;            else                ansb[i]=dpb[a[i]];            for(j=0;j<F[a[i]].size();j++)            {                int now=F[a[i]][j];                dpb[now]=i;            }        }        ll ans=0;        for(i=1;i<=n;i++)        {            int x,y;            x=a[ansa[i]];y=a[ansb[i]];            ans=ans+(ll)x*y;        }        printf("%I64d\n",ans);    }    return 0;}
HDU 4965 Fast Matrix Calculation

題意:給你矩陣A和B  分別是1000*6和6*1000的  求 C=AB  X=C^(n^2)  sum(C[i][j]%6)

思路:

利用矩陣相乘的結合律  ABABAB...ABAB = A (BA)(BA)... (BA) B 所有的BA可以處理成6*6矩陣快速冪搞  線性代數內容

代碼:


#include <iostream>#include <string.h>#include <stdio.h>using namespace std;int N;int MOD=6;typedef struct{    int m[100][100];}Matrix;void clear(Matrix &a){    memset(a.m,0,sizeof(a.m));}Matrix E;void danweiE()//單位矩陣!!!!{    int i,j;    for(i=0;i<100;i++)    for(j=0;j<100;j++)        if(i==j)E.m[i][j]=1;        else E.m[i][j]=0;}Matrix Add(Matrix a,Matrix b)  //矩陣加法(%MOD)  {      int i,j;    Matrix c;      for (i=0; i<N; i++)        for (j=0; j<N; j++)        {            c.m[i][j]=a.m[i][j]+b.m[i][j];            c.m[i][j]%=MOD;        }      return c;  }Matrix multi(Matrix a,Matrix b)//矩陣相乘!!!{    Matrix c;    int i,j,k;    clear(c);    for(i=0;i<N;i++)        for(j=0;j<N;j++)            if(a.m[i][j])            for(k=0;k<N;k++)        if(b.m[j][k])                c.m[i][k]=(c.m[i][k]+a.m[i][j]*b.m[j][k])%MOD;    return c;}Matrix matrix_mod(Matrix a,int k)//矩陣快速冪!!!{    danweiE();    Matrix ans=E,p=a;      while(k)    {        if(k&1)        {            ans=multi(ans,p);            k--;        }        k>>=1;        p=multi(p,p);    }    return ans;}int x[1010][1010],y[1010][1010],tmp[1010][1010];int n,k;Matrix a,ans;void debug(){    int i,j;    for(i=0;i<n;i++)        for(j=0;j<k;j++)            printf("%d%s",x[i][j],j==k-1?"\n":" ");    for(i=0;i<k;i++)        for(j=0;j<n;j++)            printf("%d%s",y[i][j],j==n-1?"\n":" ");        for(i=0;i<k;i++)        for(j=0;j<k;j++)            printf("%d%s",a.m[i][j],j==k-1?"\n":" ");    for(i=0;i<k;i++)        for(j=0;j<k;j++)            printf("%d%s",ans.m[i][j],j==k-1?"\n":" ");        } int main(){       int i,j,ii;    while(scanf("%d%d",&n,&k))    {        if(!n&&!k)            break;        N=k;        for(i=0;i<n;i++)        for(j=0;j<k;j++)            scanf("%d",&x[i][j]),x[i][j]%=6;        for(i=0;i<k;i++)        for(j=0;j<n;j++)            scanf("%d",&y[i][j]),y[i][j]%=6;        clear(a);        for(i=0;i<k;i++)        for(j=0;j<k;j++)        {            for(ii=0;ii<n;ii++)            {                a.m[i][j]+=y[i][ii]*x[ii][j];            }            a.m[i][j]%=6;        }        ans=matrix_mod(a,n*n-1); //算矩陣A^n次!!!!                   //debug();           for(i=0;i<n;i++)        for(j=0;j<k;j++)        {            tmp[i][j]=0;            for(ii=0;ii<k;ii++)            {                tmp[i][j]+=x[i][ii]*ans.m[ii][j];            }            tmp[i][j]%=6;        }        int ans=0;        for(i=0;i<n;i++)        for(j=0;j<n;j++)        {            int tt=0;            for(ii=0;ii<k;ii++)            {                tt+=tmp[i][ii]*y[ii][j];            }            ans+=(tt%6);        }        printf("%d\n",ans);    }    return 0;}
HDU 4968 Improving the GPA

題意:告訴你平均分和科目數  問  你能得到的最大績點和最小績點是多少

思路:

作為經常被卡績點的人  我表示這題想法來的很快- -b

對於最小績點  那麼一定是所有科目都先加到69  然後如果總分還有剩餘  就爭取把課堆到100  為什麼呢  因為69和100最浪費分 - -b

對於最大績點  一定是所有的都從60開始  然後向85堆  為什麼呢  因為反正長5分就是0.5績點  哪科長都一樣  長到85就沒有繼續的意義了

代碼:


#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 100010typedef __int64 LL;int t,n,amt;double mx,mn;double cal(int f){    if(f>=85) return 2;    if(f>=80) return 1.5;    if(f>=75) return 1;    if(f>=70) return 0.5;    return 0;}int main(){    int i,j;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&amt,&n);        amt*=n;        i=amt-n*69;        mn=n*2;        while(i>0)        {            if(i>=31)            {                mn+=2;                i-=31;            }            else            {                mn+=cal(i+69);                i=0;            }        }        i=amt-n*60;        mx=n*2;        j=0;        while(i>0&&j<n)        {            if(i>=25)            {                mx+=2;                i-=25;            }            else            {                mx+=cal(i+60);                i=0;            }            j++;        }        printf("%.4f %.4f\n",mn/n,mx/n);    }    return 0;}
HDU 4969 Just a Joke

題意:隊友看的- -b  大致就是問從圓心起跑的點在時刻保持自己與圓心與圓周上的點共線的情況下能不能在D距離內追到圓周上的點

思路:完全數學題- -b  推出來特別好寫…  也不卡精度…

代碼:


#include <iostream>#include <string.h>#include <stdio.h>#include <math.h>using namespace std;int N;int MOD=6;double v1,v2,r,d,k,a;int main(){    int i,j,ii;    int T;    scanf("%d",&T);    while(T--)    {        int aa,bb,cc,dd;        scanf("%d%d%d%d",&aa,&bb,&cc,&dd);        v1=1.0*aa;v2=1.0*bb;r=1.0*cc;d=1.0*dd;        a=r*v2/v1;        r=asin(r/a);        double ans=a*r;        if(ans>d)            printf("Why give up treatment\n");        else            printf("Wake up to code\n");    }    return 0;}
HDU 4970 Killing Monsters

題意:又是塔防遊戲…  每個塔有個攻擊範圍有個攻擊力  每個怪有個起跑位置有個血量  問幾隻怪能跑過去

思路:

從後到前掃一遍計算從x點開始到最後一共受多少傷害  (別開腦洞用什麼樹狀數組…就直接掃一遍…我很不理解為啥有人上來就資料結構…)  最後對每個怪判斷一下即可

代碼:


#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 100010typedef __int64 LL;int n,m,ans;LL sum[N],add[N];int main(){    int i,j,l,r,d;    LL ad;    while(~scanf("%d",&n))    {        if(!n) break;        memset(sum,0,sizeof(sum));        memset(add,0,sizeof(add));        scanf("%d",&m);        while(m--)        {            scanf("%d%d%d",&l,&r,&d);            add[r]+=d;            add[l-1]-=d;        }        ad=0;        for(i=n;i>=1;i--)        {            ad+=add[i];            sum[i]=sum[i+1]+ad;        }        //for(i=1;i<=n;i++) printf("%I64d  ",sum[i]);        ans=0;        scanf("%d",&m);        while(m--)        {            scanf("%I64d%d",&ad,&d);            if(sum[d]<ad) ans++;        }        printf("%d\n",ans);    }    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.