Test 2 for NOIP- Result for Day1

来源:互联网 发布:深入浅出java pdf下载 编辑:程序博客网 时间:2024/06/05 14:56

头大

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

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


Day1 (110/300)

还行,保持着A一道

T1 饼干(100/100)

题目

题目背景
CF 70A

题目描述
小美有一张很大的网格:2n*2n。

每次小美会选一个小矩阵 2x*2x ,其中 x>0,小矩阵不能超过网格的边界。然后把右上一半都放上饼干。(4个格子3个要放饼干)

每个格子不能放 2 个饼干,如果有可能,小美会尽量选择多的小矩阵,在其右上一半放上饼干。

问最少能空几个格子不放饼干?

输入格式
输入一个整数 n 。

输出格式
输出一行一个答案。如果答案太大了,就模 106+3 。

输入 
3

输出
9

数据规模
对于 100% 的数据:1≤n≤1000。

正式考试时被int ans; 阴了,ans被爆成很大的书导致后面取max时全部gg。。。后来发现我还用了快速幂但这个数据规模迭代就行了orz。
下次要仔细审题,而且赋值如果是赋为0一定要写出来。。。T_T

MY.CPP

#include <cstdio>#include <iostream>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <ctime>#include <cstdlib>#define ll long longusing namespace std;long long n,a,b,c,ans;int main(){    cin >> n;    a = 3;    b = n-1;    c = 1000003;    int ans = 1; //<=就是这个    a = a % c;    while(b>0)    {        if(b&1)           ans = (ans * a) % c;        b = b >> 1;        a = (a * a) % c;    }    cout << ans ;    return 0;}

STD.CPP

#include<bits/stdc++.h>using namespace std;int main(){    int n,ans=1;    scanf("%d",&n);    for(int i=1;i<=n-1;++i) ans=(ans*3)%1000003;    cout<<ans;    return 0;}

。。。代码短得吓人

T2 鸭舌(0/100)

题目背景
CF 77C

题目描述
小美喜欢吃鸭舌。
有一个 n 个点的树,每个节点 i ,第 i 个点上有 ai 个鸭舌。
小美一开始处于 x 号点。
每次小美可以选择一个与现在的点有边的点而且那个点还有鸭舌,那么小美会走到那个点并吃一个鸭舌。
要保证小美最后还是走到 x 号点。
问小美最多能吃几个鸭舌?

输入格式
输入第一行一个整数 n 。
接下来一行 n 个整数表示 ai 。
下面是 n-1 行每行两个整数表示一条边。
最后一行一个整数表示 x 。

输出格式
输出一行,一个整数,表示吃最多的鸭舌个数。

样例数据 1
输入  [复制]

5
1 3 1 3 2
2 5
3 4
4 5
1 5
4
输出

6
样例数据 2
输入  [复制]

3
2 1 1
3 2
1 2
3
输出

2
备注
【数据规模】
对于 30% 的数据:n≤5;ai≤5;
对于 100% 的数据:1≤n≤100000;0≤ai≤109;1≤x≤n。

关于这道题我看到是数就没去碰它了。。。orz

STD.CPP

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<cctype>#include<algorithm>#define N 100005using namespace std;int n,x,y,st,tot=0;int a[N],first[N],vis[N];long long hui[N],A[N];struct node        {            int v,next;        }edge[N*2];void read(int &x){    x=0;    int f=1;    char ch=getchar();    while(!isdigit(ch))    {        if(ch=='-') f=-1;        ch=getchar();    }    while(isdigit(ch))    {        x=(x<<3)+(x<<1)+ch-'0';        ch=getchar();    }    x=x*f;}void addedge(int x,int y){    tot++;    edge[tot].v=y;    edge[tot].next=first[x];    first[x]=tot;}long long dfs(int x){    vis[x]=true;    long long w=0,z=0;    for(int i=first[x];i;i=edge[i].next)    {        int y=edge[i].v;        if(!vis[y])        {            hui[y]=dfs(y);            w+=a[y];        }    }    int num=0;    for(int i=first[x];i;i=edge[i].next)        A[++num]=hui[edge[i].v];    if(num==0) return 0;    else    {        sort(A+1,A+num+1);        for(int i=num;(i>=1)&&(a[x]>1)&&(A[i]);i--)        {            z+=A[i];            a[x]--;        }        if(a[x]-1>=w) {a[x]-=w;z+=w;}        else {z+=a[x]-1;a[x]=1;}        a[x]--;        return z+1;    }}int main(){    //freopen("tongue.in","r",stdin);    //freopen("tongue.out","w",stdout);    memset(first,0,sizeof(first));    read(n);    for(int i=1;i<=n;++i)        read(a[i]);    for(int i=1;i<n;++i)    {        read(x),read(y);        addedge(x,y);        addedge(y,x);    }    read(st);    a[st]++;    long long ans=dfs(st);    ans=(ans-1)*2;    cout<<ans;    return 0;}

这几天要补一补树和动归。

T3 路径(10/100)

题目背景
CF 57D

题目描述
小美今天和她的好朋友在玩捉迷藏游戏。
地图可以抽象成一张 n*m 的图,地图上有一些障碍。
但这些障碍有一些性质:
1:每个障碍周围 8 个格子是没有障碍的。
2:每行每列最多只有一个障碍。
每次小美会躲在一个空地上,而她的朋友小芳会在一个空地出发寻找小美。
小美想知道如果每次小芳走 4 方向的最短路来抓她,而她们俩每次都各随机选一个空地,这个路径的平均长度是多少?

输入格式
输入第一行两个整数 n 和 m 。
接下来 n 行,每行一个长为 m 的字符串表示地图。
‘.’ 表示空地,‘X’ 表示障碍。

输出格式
输出一个小数表示平均路径长度。

样例数据 1
输入  [复制]

2 2
..
.X
输出

0.888889
样例数据 2
输入  [复制]

3 3

.X.

输出

2.000000
备注
【数据规模】
对于 30% 的数据:n,m≤50;
对于 100% 的数据:2≤n,m≤1000。

暴力枚举过了一个还是三个点,然后全部超时

MY.CPP

#include <cstdio>#include <iostream>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <ctime>#include <cstdlib>#define ll long longusing namespace std;int n,m,may[1005][1005];int xa[1005],ya[1005],jud;double ans;bool map[1005][1005];int check(){    for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++)            cout << may[i][j] << " " ;        cout << endl;    }    cout << endl;}int search(int i,int j,int x,int y){    memset(may,-1,sizeof(may));    may[i][j] = 0;    while(may[x][y]==-1)    {        for(int h=1;h<=n;h++)          for(int w=1;w<=m;w++)            if(!map[h][w])          {            if(may[h][w]==-1)may[h][w] = 9999999;            if(may[h+1][w]+1&&!map[h+1][w]) may[h][w] = min(may[h][w],may[h+1][w]+1);            if(may[h-1][w]+1&&!map[h-1][w]) may[h][w] = min(may[h][w],may[h-1][w]+1);            if(may[h][w+1]+1&&!map[h][w+1]) may[h][w] = min(may[h][w],may[h][w+1]+1);            if(may[h][w-1]+1&&!map[h][w-1]) may[h][w] = min(may[h][w],may[h][w-1]+1);            if(may[h][w]==9999999)  may[h][w] = -1;            check();          }    }    if(i==x&&j==y)  return 0;    return may[x][y];}int main(){    //freopen("length.in", "r", stdin);    //freopen("length.out", "w", stdout);    cin >> n >> m;    for(int i=1;i<=n;i++)      for(int j=1;j<=m;j++)      {        char v;        cin >> v;        if(v=='X')        {            map[i][j] = true;            xa[i]+=1;  ya[j]+=1;        }         }    for(int i=1;i<=n;i++)      for(int j=1;j<=m;j++)        if(!map[i][j])          for(int b=1;b<=n;b++)            for(int c=1;c<=m;c++)              if(!map[b][c])              {                ans += search(i,j,b,c);                jud += 1;              }    printf("%0.6lf",ans/jud);}

后来发现这实际上几乎是一道数学题。。。当时只顾着打暴力去了还以为时间没问题然后挂掉。。。准确的说是考试是没找到怎么判断什么时候加2.。还有期望刚学。。。

STD.CPP

//std answer of day1 t3#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>#include<cctype>#include<cstring>#include<string>#include<algorithm>using namespace std;const int N=1005;char s[N];int totx=0,n,m,liex[N],hangx[N];long long findans(int n,int m,int a[]){    long long res=0;    for(int i=1;i<=n;i++)    {        long long sig=0,tot=m-a[i];        for(int j=1;j<=n;j++)            if(a[j])sig+=(m-1)*abs(i-j);            else sig+=m*abs(i-j);        if(a[i])res+=(m-1)*sig;        else res+=m*sig;        if(a[i])        {            int l=i-1,r=i+1;            while(a[l]>a[l+1])                tot+=m-a[l],l--;            while(a[r]>a[r-1])                tot+=m-a[r],r++;            res+=4*tot*(a[i]-1);        }    }    return res;}int main(){  //freopen("a.in","r",stdin);  scanf("%d%d",&n,&m);  for(int i=1;i<=n;i++)  {    scanf("%s",s);    for(int j=1;j<=m;j++)      if(s[j-1]=='X')      {        hangx[i]=j;        liex[j]=i;        totx++;      }  }  int tot=n*m-totx;  double ans=(findans(n,m,hangx)+findans(m,n,liex))*1.0/tot/tot;  printf("%0.6lf",ans);  return 0;}

进步空间还很大啊。。。。。。

原创粉丝点击