Test 2 for NOIP- Result for Day1

头大

这个暑假完就要去搞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 long
using 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 100005
using 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 long
using 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;
}

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值