头大
这个暑假完就要去搞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;
}
进步空间还很大啊。。。。。。