11.5
1646. 二叉树计数
★ 输入文件:btn.in
输出文件:btn.out
简单对比
时间限制:1 s
内存限制:256 MB
【题目描述】
由 n 个节点最多可组成多少个不同形态的二叉树?
【输入格式】
一行,一个正整数 n。
【输出格式】
不同形态的二叉树的个数。
【样例输入】
2
【样例输出】
2
【提示】
【数据规模】
保证 40%的数据 n<=35;
保证 100%的数据 n<=5000。
【来源】
在此键入。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 void Emine(){ 7 freopen("btn.in","r",stdin); 8 freopen("btn.out","w",stdout); 9 } 10 struct Bigint{ 11 int a[10010],len; 12 Bigint(){memset(a,0,sizeof(a));len=0;} 13 Bigint operator = (int n){ 14 while(n){a[++len]=n%10;n/=10;} 15 } 16 Bigint operator *= (int n){ 17 int tmp=0; 18 for(int i=1;i<=len;i++){ 19 a[i]=a[i]*n+tmp; 20 tmp=a[i]/10; 21 a[i]%=10; 22 } 23 while(tmp)a[++len]=tmp%10,tmp/=10; 24 } 25 Bigint operator /= (int n){ 26 int tmp=0; 27 for(int i=len;i>=1;i--){ 28 tmp=tmp*10+a[i]; 29 a[i]=tmp/n; 30 tmp%=n; 31 } 32 while(!a[len]&&len>1)len--; 33 } 34 void prin(){for(int i=len;i>=1;i--)printf("%d",a[i]);} 35 }; 36 int main(){ 37 Emine(); 38 int n;scanf("%d",&n); 39 Bigint a;a=1; 40 for(int i=1;i<=n;i++)a*=(n+i),a/=i; 41 a/=(n+1); 42 a.prin(); 43 return 0; 44 }
1647. 上帝造题的七分钟
★★ 输入文件:god.in
输出文件:god.out
简单对比
时间限制:1 s
内存限制:256 MB
【题目描述】
一群神牛在造题:
"第一分钟,X说,要有数列,于是便给定了一个正整数数列。
第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作。
第三分钟,k说,要能查询,于是便有了求一段数的和的操作。
第四分钟,彩虹喵说,要是noip难度,于是便有了数据范围。
第五分钟,诗人说,要有韵律,于是便有了时间限制和内存限制。
第六分钟,和雪说,要省点事,于是便有了保证运算过程中及最终结果均不超过64位有符号整数类型的表示范围的限制。
第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。"
所以这个神圣的任务就交给你了。
【输入格式】
第一行一个整数n,代表数列中数的个数。
第二行n个正整数,表示初始状态下数列中的数。
第三行一个整数m,表示有m次操作。
接下来m行每行三个整数k,l,r,k=0表示给[l,r]中的每个数开平方(下取整),k=1表示询问[l,r]中各个数的和。
【输出格式】
对于每个询问操作,在一行输出一个回答。
【输入样例】
10
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8
【输出样例】
19
7
6
【数据规模】
对于30%的数据,1<=n,m<=1000,数列中的数不超过32767。
对于100%的数据,1<=n,m<=100000,1<=l<=r<=n,数列中的数大于0,且不超过1e12。
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #define maxn 100010 7 #define LL long long 8 #define Ll l,mid,rt<<1 9 #define Rr mid+1,r,rt<<1|1 10 using namespace std; 11 LL n,m,a[maxn],num[maxn<<2],maxx[maxn<<2]; 12 void Emine(){ 13 freopen("god.in","r",stdin); 14 freopen("god.out","w",stdout); 15 } 16 LL read(){ 17 LL x=0,f=1;char ch=getchar(); 18 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 19 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 void pushup(int rt){num[rt]=num[rt<<1]+num[rt<<1|1];maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);} 23 void build(int l,int r,int rt){ 24 if(l==r){num[rt]=maxx[rt]=a[l];return;} 25 int mid=(l+r)>>1; 26 build(Ll);build(Rr); 27 pushup(rt); 28 } 29 void change(int ql,int qr,int l,int r,int rt){ 30 if(l==r){num[rt]=sqrt(num[rt]),maxx[rt]=sqrt(maxx[rt]);return;} 31 int mid=(l+r)>>1; 32 if(ql<=mid&&maxx[rt<<1]>1)change(ql,qr,Ll); 33 if(mid<qr&&maxx[rt<<1|1]>1)change(ql,qr,Rr); 34 pushup(rt); 35 } 36 LL query(int ql,int qr,int l,int r,int rt){ 37 if(ql<=l&&r<=qr)return num[rt]; 38 int mid=(l+r)>>1;LL tmp=0; 39 if(ql<=mid)tmp+=query(ql,qr,Ll); 40 if(mid<qr)tmp+=query(ql,qr,Rr); 41 return tmp; 42 } 43 int main(){ 44 Emine(); 45 n=read();for(int i=1;i<=n;i++)a[i]=read();build(1,n,1); 46 m=read();for(int i=1;i<=m;i++){ 47 int Q=read(),l=read(),r=read(); 48 if(!Q)change(l,r,1,n,1); 49 else printf("%lld\n",query(l,r,1,n,1)); 50 } 51 return 0; 52 }
1648. 水叮当的舞步
★★☆ 输入文件:floodit.in
输出文件:floodit.out
简单对比
时间限制:1 s
内存限制:256 MB
【题目描述】
地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色。
水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色。这里连通定义为:两个格子有公共边,并且颜色相同。
由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她想知道最少要多少步才能把所有格子的颜色变成一样的。
【输入格式】
每个测试点包含多组数据。
每组数据的第一行是一个整数N,表示地摊上的格子有N行N列。
接下来一个N*N的矩阵,矩阵中的每个数都在0~5之间,描述了每个格子的颜色。
N=0代表输入的结束。
【输出格式】
对于每组数据,输出一个整数,表示最少步数。
【样例输入】
2 0 0 0 0 3 0 1 2 1 1 2 2 2 1 0
【样例输出】
0 3
【提示】
数据规模:
对于30%的数据,N<=5
对于50%的数据,N<=6
对于70%的数据,N<=7
对于100%的数据,N<=8,每个测试点不多于20组数据。
【来源】
在此键入。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define maxn 10 6 using namespace std; 7 void Emine(){ 8 freopen("floodit.in","r",stdin); 9 freopen("floodit.out","w",stdout); 10 } 11 const int dx[4]={-1,0,0,1},dy[4]={0,-1,1,0}; 12 int a[maxn][maxn],v[maxn][maxn],f[maxn],n,ida; 13 void dfs(int x,int y,int color){ //左上角格子所在联通块的格子标记为1。周围一圈格子标记为2,其它格子标记为0 14 v[x][y]=1; 15 for(int i=0;i<4;i++){ 16 int nx=x+dx[i],ny=y+dy[i]; 17 if(nx<1||ny<1||nx>n||ny>n||v[nx][ny]==1)continue; 18 v[nx][ny]=2; 19 if(a[nx][ny]==color)dfs(nx,ny,color); 20 } 21 } 22 int gj(){ //估价函数,如果当前矩阵中除了左上角的联通块之外,共有M种颜色,那么还需要的步数不小于M。 23 int i,j,tmp=0; 24 memset(f,0,sizeof(f)); 25 for(int i=1;i<=n;i++) 26 for(int j=1;j<=n;j++) 27 if(!f[a[i][j]]&&v[i][j]!=1){f[a[i][j]]=1;tmp++;} 28 return tmp; 29 } 30 int fill(int color){ //填颜色 31 int tmp=0; 32 for(int i=1;i<=n;i++) 33 for(int j=1;j<=n;j++) 34 if(a[i][j]==color&&v[i][j]==2){tmp++;dfs(i,j,color);} 35 return tmp; 36 } 37 bool IDA(int step){ //IDA*优化 38 int g=gj(); 39 if(step+g>ida)return 0; //当前搜索深度+估价函数的值>深度限制,可以回溯。 40 if(!g)return 1; 41 int w[maxn][maxn]; 42 for(int i=0;i<=5;i++){ 43 memcpy(w,v,sizeof(v)); 44 if(fill(i)&&IDA(step+1))return 1; 45 memcpy(v,w,sizeof(w)); 46 } 47 return 0; 48 } 49 int main(){ 50 Emine(); 51 while(cin>>n&&n){ 52 for(int i=1;i<=n;i++) 53 for(int j=1;j<=n;j++) 54 cin>>a[i][j]; 55 memset(v,0,sizeof(v)); 56 dfs(1,1,a[1][1]); 57 for(ida=0;;ida++)if(IDA(0))break; 58 cout<<ida<<endl; 59 } 60 return 0; 61 }