Test 4 for NOIP- Result for Day2

来源:互联网 发布:coc地狱塔数据 编辑:程序博客网 时间:2024/06/01 08:27

头大

这个暑假完就要去搞NOIP了。。。

暑假55天也就20次测试。。。为防万一我还是每次测试玩都写个总结。。


终于在经过两周的煎熬后我终于能考好一次了。。莫名感动(可能是吧)
据曾老说这次给我们出题的是上一届的(noi还是noip?)金牌选手给我们出的,然后三个题的背景都不一样。。。【COCI AKCIJA,Codechef STDYTAB,CEOI BOARD】看着也是一脸懵逼。
不过这个分还是没上200,如果是110来计的话就能上270了还是不错,可以给原来成外的装个逼(hh)

Day2 (166/300)

T1 Bookstore(100/100)

题目背景
SOURCE:NOIP2016-RZZ-2 T1

题目描述
在遥远的汪星球,小W开了一家书店。

这家书店推出促销活动,即每次顾客可以选择三本书,然后可以免去其中最便宜的那本书的价格(也就是只需要支付最贵的两本书的价格之和的钱,就能买到这三本书)。当然,如果顾客选择的书不足三本,那么就只能付全部的价钱了。

现在,有一个顾客挑选了 n 本书,这个顾客想要知道,自己最少付多少钱可以买到全部的书?

输入格式
输入 n+1 行,第一行一个整数 n ,表示顾客要买的书的本书。
接下来 n 行,每行一个整数,表示每本书的价钱。

输出格式
输出一行,表示顾客最少要付多少钱。

样例数据 1
输入  [复制]

4
3
2
3
2
输出

8
备注
【数据规模与约定】
对于 50% 的数据,n≤2000。
对于 100% 的数据,1≤n≤100000,1≤ci≤100000。

智障暴力题。不过当时做完我还很不放心的回去检查了好几遍。。被T1坑得怕了。
每次比赛总有人被T1坑。

STD.CPP

#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>#include<algorithm>#include<string>#include<cstring>#include<queue>using namespace std;long long n=0,a[100005],ans=0;int main(){    freopen("bookstore.in","r",stdin);    freopen("bookstore.out","w",stdout);        memset(a,0,sizeof(a));    cin >> n;    for(int i=1;i<=n;i++)       {        cin >> a[i];        ans += a[i];    }    sort(a+1,a+n+1);    while(n-2>=0)    {        ans -= a[n-2];        n-=3;    }    cout << ans;}

T2 Table(60/100)

题目背景
SOURCE:NOIP2016-RZZ-2 T2

题目描述
给定一个 n×m 的矩阵,行列均从 1 开始标号。

一个矩阵被认为是稳定的,当且仅当对于任意的 2≤i≤n,第 i 行的数的和不小于第 i−1 行的数的和,且最后一行的数的和小于等于 m ,并且要求矩阵中所有的元素都是非负的。

求所有 n×m 的稳定矩阵的方案数,答案对 109 取模。

输入格式
第一行一个整数 T ,表示数据组数。
每组数据一行两个整数 n,m 。

输出格式
输出 T 行,每行一个整数,表示方案数。

样例数据 1
输入  [复制]

3
1 1
2 2
2 3
输出

2
25
273
备注
【数据规模与约定】
对于 30% 的数据,n,m≤3。
对于 60% 的数据,n,m≤50。
对于 100% 的数据,1≤n,m≤2000;1≤T≤10。

MY.CPP

#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>#include<algorithm>#include<string>#include<cstring>#include<queue>using namespace std;int n,m,t,ans;int dp1[2005][2005],dp2[2005][2005]; const int maxx = 1000000000;//   dp1[当前个数][当前总合]=方案数        dp2[当前行数][当前总合]=方案数 int main(){    freopen("table.in","r",stdin);    freopen("table.out","w",stdout);    cin >> t;    while(t--)    {        memset(dp1,0,sizeof(dp1));        memset(dp2,0,sizeof(dp2));        cin >> n >> m;        for(int i=0;i<=m;i++)            dp1[1][i] = 1;        for(int i=2;i<=m;i++)          for(int j=0;j<=m;j++)            for(int k=0;k<=j;k++)            {                dp1[i][j] += dp1[i-1][j-k];                dp1[i][j] %= maxx;            }        for(int i=0;i<=m;i++)          dp2[1][i] = dp1[m][i];        for(int i=2;i<=n;i++)           for(int j=0;j<=m;j++)                 for(int k=0;k<=j;k++)             {                dp2[i][j] += (dp2[i-1][k]*dp1[m][j]);                dp2[i][j] %= maxx;            }        for(int i=0;i<=m;i++)        {            ans += dp2[n][i];            ans %= maxx;        }        cout << ans << endl;        ans = 0;    }}

头一次正确地使用了Dp。。两个Dp一个预处理一个递推答案,以n^3的时间复杂度过了60%而且事后只需要优化就能得标答也是把我也吓一跳。
Dp真是一个神奇的东西。
题解就是用前缀和等各种方法把n^3的时间复杂度降成了n^2。

STD.CPP

#include<cstdio>#include<algorithm>#include<cmath>#include<ctime>#include<iomanip>#include<iostream>#include<cstring>#include<string>#include<cctype>using namespace std;const int mod=1e9;int n,m,T,dp[2001][2001],c[4002][4002];//---------------------inline int Readint(){    int i=0,f=1; char ch;    for(ch=getchar();(ch<'0'||ch>'9');ch=getchar());    for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<1)+(i<<3)+ch-'0';    return i*f;}//---------------------int main(){    //freopen("table.in","r",stdin);    //freopen("table.out","w",stdout);   for(int i=0;i<=4001;i++) c[i][0]=1,c[i][i]=1;   for(int i=1;i<=4001;i++)     for(int j=1;j<=i;j++){        c[i][j]=c[i-1][j-1]+c[i-1][j];        c[i][j]%=mod;     }    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&m);        memset(dp,0,sizeof(dp));        for(int i=0;i<=m;i++) dp[0][i]=1;        for(int i=1;i<=n;i++){          for(int j=0;j<=m;j++){            long long now=dp[i-1][j];            now=(now*c[j+m-1][m-1])%mod;            if(j) dp[i][j]=dp[i][j-1]+now;            else dp[i][j]=now;            dp[i][j]=dp[i][j]%mod;          }        }        cout<<dp[n][m]<<endl;    }    return 0;}

T3 Board(6/100)

题目背景
SOURCE:NOIP2016-RZZ-2 T3

题目描述
给出这样一棵“二叉树”:

每个节点有左右两个儿子,并如下定义每个节点的高度:假设父亲节点的高度为 h ,那么他的两个儿子的节点的高度都是 h + 1 ,相同高度的所有节点称作一层。
每个节点的左儿子的子树都在右儿子的子树的左边,每一层相邻的两个节点之间有一条边。
下面是一个例子:
奇怪的二叉树
每一条图上的路径用一个字符串表示,字符串中的每一个字符表示一个移动。字符仅包含如下五种:

1:表示移动到当前节点的左儿子
2:表示移动到当前节点的右儿子
U:表示移动到当前节点的父亲节点
L:表示移动到当前节点同层的左边的节点(保证当前节点在这一层中不是最左边的节点)
R:表示移动到当前节点同层的右边的节点(保证当前节点在这一层中不是最右边的节点)
用一条路径来表示这条路径的终点,例如路径:221LU 就表示上图中的节点 A 。

给出两条路径,你的任务是求出着两条路径的终点之间的最短路。

输入格式
输入两行,每行一个字符串,分别表示两条路径。

输出格式
输出一行一个整数,表示能得到的串的总数。

样例数据 1
输入  [复制]

221LU
12L2
输出

3
备注
【数据规模与约定】
用 D 表示所有经过的节点中,深度最大的节点的深度;S 表示输入字符串的最大长度。
对于 10% 的数据,D≤10。
对于 30% 的数据,D≤50。
对于 50% 的数据,D≤1000。
对于 70% 的数据,D≤20000。
对于 100% 的数据,D≤100000;S≤100000。

MY.CPP

#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>#include<cctype>#include<cstring>#include<string>#include<algorithm>using namespace std;int n, s, cnt = 0;int stack[200050], hash[70000], check[70000];char c[5], num[20];void cint(int aq,int cnt){    int ans=0,i;    for(i=1;i<=cnt;i++)    {        if(hash[stack[i]])        {          int h1 = stack[i];          int h2 = aq;          if((h1&h2)==stack[i])            ans += hash[stack[i]];        }    }    cout << ans << endl;}bool comp(int a,int b){    return a>b;}int init(int cnt,int flag){    sort(stack+1,stack+cnt+1,comp);    if(flag)    cnt-=1;    for(int i=1;i<=cnt;i++)        check[stack[i]] = i;    return cnt;}int main(){    int y=0;    cin >> n;    while(n--)    {        int flag=0;        scanf("%s",c);  cin >> s;        if(c[0]=='a')   {hash[s]+=1;if(hash[s]==1)stack[++cnt]=s;}        else if(c[0]=='d')  {hash[s]-=1;if(hash[s]==0)stack[check[s]]=0,check[s]=0,flag = 1;}        else if(c[0]=='c')  {cint(s,cnt);y+=1;}        cnt = init(cnt,flag);    }}

一开始看见二叉树三个字我以为T3又是送。
看了半个小时后。。。坚决放弃。(我以为可以算出每个数的值结果深度可达100000连高精度都撑不住2^100000的巨大数字。)
别问我那3个点我是怎么过的。我也不知道。。orz
话说这次给的测试点真的多。。。50个。。中欧人这么有时间出数据?

STD’.CPP

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<cmath>using namespace std;const int Maxn=1e5+50;int BITA[Maxn],BITB[Maxn],nowbitA=1,nowbitB=1,_;char ch[Maxn];inline void delA(int nowbit,int val){    if(val==1)    {        if(BITA[nowbit]==1)        {            BITA[nowbit]=0;            return;        }        else        {            BITA[nowbit]=1;            delA(nowbit-1,val);        }    }    else    {        if(BITA[nowbit]==0)        {            BITA[nowbit]=1;            return;        }        else        {            BITA[nowbit]=0;            delA(nowbit-1,val);        }    }}inline void delB(int nowbit,int val){    if(val==1)    {        if(BITB[nowbit]==1)        {            BITB[nowbit]=0;            return;        }        else        {            BITB[nowbit]=1;            delB(nowbit-1,val);        }    }    else    {        if(BITB[nowbit]==0)        {            BITB[nowbit]=1;            return;        }        else        {            BITB[nowbit]=0;            delB(nowbit-1,val);        }    }}inline int power(int x,int y){    int res=1;    while(y)    {        if(y&1)res*=x;        x*=x;        y>>=1;    }    return res;}int dis[Maxn*2],bg,maxd;inline void calcA(){    for(int i=2;i<=nowbitA;i++)    {        --bg;        if(BITA[i]==0){if(BITB[i]==1)dis[bg]++;if(!maxd)maxd=bg;}        else{if(BITB[i]==0)dis[bg]--;}    }}inline void calcB(){    for(int i=2;i<=nowbitA;i++)    {        --bg;        if(BITB[i]==0){if(BITA[i]==1)dis[bg]++;if(!maxd)maxd=bg,_=1;}        else{if(BITA[i]==0)dis[bg]--;}    }}inline bool Isl(){    for(int i=2;i<=nowbitA;i++)    {        if(BITA[i]==0&&BITB[i]==1)return true;        if(BITA[i]==1&&BITB[i]==0)return false;    }   }inline int calcdis(){    int t=0,bz=0;    for(int i=bg;i<=maxd;i++)    {        if(dis[i])t+=dis[i]*power(2,(i-bg));    }    return t;}inline bool judgesame(){    if(nowbitA!=nowbitB)return false;    for(int i=1;i<=nowbitA;i++)if(BITA[i]^BITB[i])return false;    return true;}int main(){    BITA[nowbitA]=BITB[nowbitB]=1;    scanf("%s",ch+1);    int len=strlen(ch+1);    for(int i=1;i<=len;i++)    {        if(ch[i]=='1')        {            nowbitA++;            BITA[nowbitA]=0;        }        else if(ch[i]=='2')        {            nowbitA++;            BITA[nowbitA]=1;        }        else if(ch[i]=='U'){nowbitA--;}        else if(ch[i]=='L'){delA(nowbitA,1);}        else delA(nowbitA,-1);    }    scanf("%s",ch+1);    len=strlen(ch+1);    for(int i=1;i<=len;i++)    {        if(ch[i]=='1')        {            nowbitB++;            BITB[nowbitB]=0;        }        else if(ch[i]=='2')        {            nowbitB++;            BITB[nowbitB]=1;        }        else if(ch[i]=='U'){nowbitB--;}        else if(ch[i]=='L'){delB(nowbitB,1);}        else delB(nowbitB,-1);    }    if(judgesame())cout<<0<<endl;    else    {    int ans=0;    if(nowbitA>nowbitB){ans+=(nowbitA-nowbitB);nowbitA=nowbitB;}    else {ans+=(nowbitB-nowbitA);nowbitB=nowbitA;}    bg=nowbitA;    if(Isl())calcA();    else calcB();    while(1)    {        if(maxd-bg>=25)        {            bg++,nowbitA--,nowbitB--;ans+=2;        }        else        {            int t1=calcdis();            bg++,nowbitA--,nowbitB--;            int t2=calcdis();            if(t1>=(t2+2))ans+=2;            else            {                ans+=t1;                break;            }        }    }    cout<<ans<<endl;    }}

这次代码长的吓人。。还用了线段树也是够拼。

成功的脱了一次非入了一次欧orz。

原创粉丝点击