第五届图灵杯中级组题解
赛时得分 \(25+50+5+1=81\),rk 67,逊死了。
赛后发现 T1 爆搜 + 剪枝有 \(50\) 分,我【】【】。
总结:还是菜。
A. 等差数列
首先特判 \(n\le 4\) 的情况。此时答案必然为 Yes
,只需要两两分组即可。
由于第一个数必然在其中一个等差数列内,不妨强制令其在第一个等差数列内。
考虑 DFS。维护以下信息:当前是第几个数,第一个等差数列的公差、末尾(还没加入当前数)和第二个等差数列的公差、末尾。函数为 bool
类型,表示能否分成两个等差数列。
考虑如下搜索策略:首先在第二个等差数列没有数的情况下,能选第一段就选,实际上相当于选了一个前缀。前缀选完之后再正常选两段,分成第一个、第二个、第三个即以后三种情况讨论。搜索时还可以加几个小剪枝。
讨论过程稍微有些复杂,具体见代码:
#include<bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#define gt getchar
#define pt putchar
//typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 lll;
//typedef __uint128_t ulll;
const int N=5e5+5;
using namespace std;
inline bool __(char ch){return ch>=48&&ch<=57;}
inline int read(){
int x=0;bool sgn=0;char ch=gt();
while(!__(ch)&&ch!=EOF) sgn|=(ch=='-'),ch=gt();
while(__(ch)) x=(x<<1)+(x<<3)+(ch&15),ch=gt();
return sgn?-x:x;
}
template<class T> inline void print(T x){
static char st[70];short top=0;
if(x<0)pt('-');
do{st[++top]=x>=0?(x%10+48):(-(x%10)+48),x/=10;}while(x);
while(top)pt(st[top--]);
}
template<class T> inline void printsp(T x){
print(x);
putchar(' ');
}
template<class T> inline void println(T x){
print(x);
putchar('\n');
}
inline void put_str(string s){
int siz=s.size();
for(int i=0;i<siz;++i) pt(s[i]);
printf("\n");
}
int T,n,a[N];
bool dfs(int now,int x_1,int x_2,int d_1,int d_2){
// 当前搜索到第 now 个
// 第一个等差数列当前的最后一项为 x_1,公差为 d_1
// 第二个等差数列当前的最后一项为 x_2,公差为 d_2
if(now>n) return 1;
if(x_1==-1){
// 第一个等差数列的第一个(就是 a[1])
return dfs(now+1,a[now],x_2,d_1,d_2);
}
if(x_2==-1&&x_1!=-1&&d_1!=-1&&a[now]-x_1==d_1){
// 第一个等差数列第三个及其后面的数,且第二个等差数列没有数,先全接上(前缀)
return dfs(now+1,a[now],x_2,d_1,d_2);
}
bool ok=0;
if(x_2==-1){
// 第二个等差数列的第一个
ok|=dfs(now+1,x_1,a[now],d_1,d_2);
}
if(ok) return 1;
if(d_1==-1){
// 第一个等差数列的第二个
ok|=dfs(now+1,a[now],x_2,a[now]-x_1,d_2);
}
if(ok) return 1;
if(x_2!=-1&&d_2==-1){
// 第二个等差数列的第二个
ok|=dfs(now+1,x_1,a[now],d_1,a[now]-x_2);
}
if(ok) return 1;
if(x_1!=-1&&d_1!=-1&&a[now]-x_1==d_1){
// 第一个等差数列的第三个及后面的数
ok|=dfs(now+1,a[now],x_2,d_1,d_2);
}
if(ok) return 1;
if(x_2!=-1&&d_2!=-1&&a[now]-x_2==d_2){
// 第二个等差数列的第三个及后面的数
ok|=dfs(now+1,x_1,a[now],d_1,d_2);
}
return ok;
}
signed main(){
T=read();
while(T--){
n=read();
for(int i=1;i<=n;++i) a[i]=read();
if(n<=4) printf("Yes\n");
else printf(dfs(1,-1,-1,-1,-1)?"Yes\n":"No\n");
}
return 0;
}
B. 鱼棋
考虑 BFS。
对每种棋子维护两个偏移量数组。变身、王、马的转移比较显然。对于车和象,可以枚举走的长度,那么坐标的变化量就是 \(\text{长度}\times\text{偏移量}\),遇到障碍就 break 即可。
小优化:如果搜索中途已经到达终点,那么直接输出答案走人即可。但是这个时候队列可能没有清空(如果定义在全局),那么下次 BFS 的时候不要忘记清空。
最后的问题就是坐标有点大,用 map
维护即可。
这实际上就是我的赛时做法,我写了 \(158\) 行。
代码:
#include<bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#define gt getchar
#define pt putchar
//typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 lll;
//typedef __uint128_t ulll;
const int dx_w[]={-1,-1,-1,0,1,1,1,0};
const int dy_w[]={-1,0,1,1,1,0,-1,-1};
const int dx_m[]={-1,-2,-2,-1,1,2,2,1};
const int dy_m[]={-2,-1,1,2,2,1,-1,-2};
const int dx_c[]={-1,1,0,0};
const int dy_c[]={0,0,-1,1};
const int dx_x[]={-1,-1,1,1};
const int dy_x[]={-1,1,-1,1};
using namespace std;
inline bool __(char ch){return ch>=48&&ch<=57;}
inline int read(){
int x=0;bool sgn=0;char ch=gt();
while(!__(ch)&&ch!=EOF) sgn|=(ch=='-'),ch=gt();
while(__(ch)) x=(x<<1)+(x<<3)+(ch&15),ch=gt();
return sgn?-x:x;
}
template<class T> inline void print(T x){
static char st[70];short top=0;
if(x<0)pt('-');
do{st[++top]=x>=0?(x%10+48):(-(x%10)+48),x/=10;}while(x);
while(top)pt(st[top--]);
}
template<class T> inline void printsp(T x){
print(x);
putchar(' ');
}
template<class T> inline void println(T x){
print(x);
putchar('\n');
}
inline void put_str(string s){
int siz=s.size();
for(int i=0;i<siz;++i) pt(s[i]);
printf("\n");
}
int T,n,m,sx,sy,tx,ty,cnt;
char now;
map<int,map<int,char> >mp;
inline bool outmp(int x,int y){
return x<1||x>n||y<1||y>m;
}
inline int id(char opt){
if(opt=='K') return 1;
else if(opt=='N') return 2;
else if(opt=='R') return 3;
return 4;
}
map<int,map<int,bool> >not_go;
map<int,map<int,map<int,bool> > >vis;
map<int,map<int,map<int,int> > >dis;
struct Pair{
int x,y,id;
Pair(int _x=0,int _y=0,int _id=0)
:x(_x),y(_y),id(_id)
{}
};
queue<Pair>q;
inline void bfs(){
while(q.size()) q.pop();
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) for(int k=1;k<=4;++k) vis[i][j][k]=dis[i][j][k]=0;
q.push(Pair(sx,sy,id(now)));
vis[sx][sy][id(now)]=1,dis[sx][sy][id(now)]=0;
while(q.size()){
int x=q.front().x,y=q.front().y,opt=q.front().id;
q.pop();
for(int i=1;i<=4;++i){
if(vis[tx][ty][i]==1){
println(dis[tx][ty][i]);
return;
}
}
for(int i=1;i<=4;++i){
if(opt!=i){
// 切换
if(vis[x][y][i]==1) continue;
vis[x][y][i]=1;
dis[x][y][i]=dis[x][y][opt]+1;
q.push(Pair(x,y,i));
}
}
if(opt==1){
for(int i=0;i<8;++i){
int xx=x+dx_w[i],yy=y+dy_w[i];
if(outmp(xx,yy)||vis[xx][yy][opt]==1||not_go[xx][yy]==1) continue;
q.push(Pair(xx,yy,opt));
vis[xx][yy][opt]=1;
dis[xx][yy][opt]=dis[x][y][opt]+1;
}
}else if(opt==2){
for(int i=0;i<8;++i){
int xx=x+dx_m[i],yy=y+dy_m[i];
if(outmp(xx,yy)||vis[xx][yy][opt]==1||not_go[xx][yy]==1) continue;
q.push(Pair(xx,yy,opt));
vis[xx][yy][opt]=1;
dis[xx][yy][opt]=dis[x][y][opt]+1;
}
}else if(opt==3){
for(int i=0;i<4;++i){
for(int len=1;;++len){
int xx=x+len*dx_c[i],yy=y+len*dy_c[i];
if(outmp(xx,yy)) break;
if(vis[xx][yy][opt]==1) continue;
if(not_go[xx][yy]==1) break;
q.push(Pair(xx,yy,opt));
vis[xx][yy][opt]=1;
dis[xx][yy][opt]=dis[x][y][opt]+1;
}
}
}else{
for(int i=0;i<4;++i){
for(int len=1;;++len){
int xx=x+len*dx_x[i],yy=y+len*dy_x[i];
if(outmp(xx,yy)) break;
if(vis[xx][yy][opt]==1) continue;
if(not_go[xx][yy]==1) break;
q.push(Pair(xx,yy,opt));
vis[xx][yy][opt]=1;
dis[xx][yy][opt]=dis[x][y][opt]+1;
}
}
}
}
for(int i=1;i<=4;++i){
if(vis[tx][ty][i]==1){
println(dis[tx][ty][i]);
return;
}
}
println(-1);
}
signed main(){
T=read();
while(T--){
n=read(),m=read();
cin>>now;
sx=sy=tx=ty=cnt=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
cin>>mp[i][j];
not_go[i][j]=0;
if(mp[i][j]=='S') sx=i,sy=j;
if(mp[i][j]=='T') tx=i,ty=j;
if(mp[i][j]=='#') cnt++,not_go[i][j]=1;
}
}
bfs();
}
return 0;
}
分析一下上述算法的复杂度:变身、王和马的转移复杂度都是 \(O(1)\) 的,没有问题。但车和象转移时枚举的长度可能达到 \(O(n)\) 级别,所以复杂度是 \(O(n^3\log n)\)(map),过不了,只有 \(50\) 分。
注:这里 \(n,m\) 同级,时间复杂度分析时就只用 \(n\) 不用 \(m\) 了。
考虑剪枝:车、象如果在转移前,发现当前点已经被之前的同种类棋子从相同方向更新过了,那么直接 continue,切换到下一个方向。然后在搜索的过程中顺便记录下有没有经过即可。注意如果之前已经被访问过了也要标记,便于后面的剪枝。
对于车来说,上下、左右分别为两个方向;对于象来说,主对角线、副对角线分别为两个方向。
注意 map 还是太慢了,所以我们可以换成 unordered_map 加速。
这样可以拿到 \(65\) 分,还是过不了。
仔细思考一下,umap 的速度还是太慢了,注意到 \(n\times m\le 10^6\),所以用两维来存坐标太浪费了。我们可以将坐标降为一维,然后用普通数组存即可。
时间复杂度 \(O(n^2)\),可以通过。
最后,由于 cin 读入字符太慢了,而且 getchar 会出现各种奇怪的错误,因此我手写了一个 getchar。
此时代码长度来到了 \(185\) 行,并且我把清空操作放到了一个函数里。
代码:
#include<bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#define gt getchar
#define pt putchar
//typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 lll;
//typedef __uint128_t ulll;
const int N=1e6+5;
const int dx_w[]={-1,-1,-1,0,1,1,1,0};
const int dy_w[]={-1,0,1,1,1,0,-1,-1};
const int dx_m[]={-1,-2,-2,-1,1,2,2,1};
const int dy_m[]={-2,-1,1,2,2,1,-1,-2};
const int dx_c[]={-1,1,0,0};
const int dy_c[]={0,0,-1,1};
const int dx_x[]={-1,1,-1,1};
const int dy_x[]={-1,1,1,-1};
using namespace std;
inline bool __(char ch){return ch>=48&&ch<=57;}
inline int read(){
int x=0;bool sgn=0;char ch=gt();
while(!__(ch)&&ch!=EOF) sgn|=(ch=='-'),ch=gt();
while(__(ch)) x=(x<<1)+(x<<3)+(ch&15),ch=gt();
return sgn?-x:x;
}
template<class T> inline void print(T x){
static char st[70];short top=0;
if(x<0)pt('-');
do{st[++top]=x>=0?(x%10+48):(-(x%10)+48),x/=10;}while(x);
while(top)pt(st[top--]);
}
template<class T> inline void printsp(T x){
print(x);
putchar(' ');
}
template<class T> inline void println(T x){
print(x);
putchar('\n');
}
inline void put_str(string s){
int siz=s.size();
for(int i=0;i<siz;++i) pt(s[i]);
printf("\n");
}
int T,n,m,sx,sy,tx,ty,cnt;
char now,mp[N];
inline char getc(){
char ch=gt();
while(ch==' '||ch=='\n'||ch=='\r') ch=gt();
return ch;
}
inline int get_id(int x,int y){
return (x-1)*m+y;
}
inline bool outmp(int x,int y){
return x<1||x>n||y<1||y>m;
}
inline int id(char opt){
if(opt=='K') return 1;
else if(opt=='N') return 2;
else if(opt=='R') return 3;
return 4;
}
bool not_go[N],vis[N][5],che[N][5],ele[N][5];
int dis[N][5];
struct Pair{
int x,y,id;
Pair(int _x=0,int _y=0,int _id=0)
:x(_x),y(_y),id(_id)
{}
};
queue<Pair>q;
inline void clear(){
while(q.size()) q.pop();
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){
che[get_id(i,j)][0]=che[get_id(i,j)][1]=0;
ele[get_id(i,j)][0]=ele[get_id(i,j)][1]=0;
for(int k=1;k<=4;++k) vis[get_id(i,j)][k]=0,dis[get_id(i,j)][k]=0;
}
}
inline void bfs(){
clear();
q.push(Pair(sx,sy,id(now)));
vis[get_id(sx,sy)][id(now)]=1,dis[get_id(sx,sy)][id(now)]=0;
while(q.size()){
int x=q.front().x,y=q.front().y,opt=q.front().id;
q.pop();
int ans=1e9;
for(int i=1;i<=4;++i){
if(vis[get_id(tx,ty)][i]==1){
ans=min(ans,dis[get_id(tx,ty)][i]);
}
}
if(ans!=1e9){
println(ans);
return;
}
for(int i=1;i<=4;++i){
if(opt!=i){
// 切换
if(vis[get_id(x,y)][i]==1) continue;
vis[get_id(x,y)][i]=1;
dis[get_id(x,y)][i]=dis[get_id(x,y)][opt]+1;
q.push(Pair(x,y,i));
}
}
if(opt==1){
for(int i=0;i<8;++i){
int xx=x+dx_w[i],yy=y+dy_w[i];
if(outmp(xx,yy)||vis[get_id(xx,yy)][opt]==1||not_go[get_id(xx,yy)]==1) continue;
q.push(Pair(xx,yy,opt));
vis[get_id(xx,yy)][opt]=1;
dis[get_id(xx,yy)][opt]=dis[get_id(x,y)][opt]+1;
}
}else if(opt==2){
for(int i=0;i<8;++i){
int xx=x+dx_m[i],yy=y+dy_m[i];
if(outmp(xx,yy)||vis[get_id(xx,yy)][opt]==1||not_go[get_id(xx,yy)]==1) continue;
q.push(Pair(xx,yy,opt));
vis[get_id(xx,yy)][opt]=1;
dis[get_id(xx,yy)][opt]=dis[get_id(x,y)][opt]+1;
}
}else if(opt==3){
for(int i=0;i<4;++i){
if(che[get_id(x,y)][i/2]) continue;
for(int len=1;;++len){
int xx=x+len*dx_c[i],yy=y+len*dy_c[i];
if(outmp(xx,yy)) break;
if(vis[get_id(xx,yy)][opt]){
che[get_id(xx,yy)][i/2]=1;
continue;
}
if(not_go[get_id(xx,yy)]==1) break;
q.push(Pair(xx,yy,opt));
vis[get_id(xx,yy)][opt]=1;
che[get_id(xx,yy)][i/2]=1;
dis[get_id(xx,yy)][opt]=dis[get_id(x,y)][opt]+1;
}
}
}else{
for(int i=0;i<4;++i){
if(ele[get_id(x,y)][i/2]) continue;
for(int len=1;;++len){
int xx=x+len*dx_x[i],yy=y+len*dy_x[i];
if(outmp(xx,yy)) break;
if(not_go[get_id(xx,yy)]==1) break;
if(vis[get_id(xx,yy)][opt]){
ele[get_id(xx,yy)][i/2]=1;
continue;
}
q.push(Pair(xx,yy,opt));
vis[get_id(xx,yy)][opt]=1;
ele[get_id(xx,yy)][i/2]=1;
dis[get_id(xx,yy)][opt]=dis[get_id(x,y)][opt]+1;
}
}
}
}
int ans=1e9;
for(int i=1;i<=4;++i){
if(vis[get_id(tx,ty)][i]==1){
ans=min(ans,dis[get_id(tx,ty)][i]);
}
}
println(ans==1e9?-1:ans);
}
signed main(){
T=read();
while(T--){
n=read(),m=read(),now=getc();
gt();
sx=sy=tx=ty=cnt=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
mp[get_id(i,j)]=getc(),not_go[get_id(i,j)]=0;
if(mp[get_id(i,j)]=='S') sx=i,sy=j;
if(mp[get_id(i,j)]=='T') tx=i,ty=j;
if(mp[get_id(i,j)]=='#') cnt++,not_go[get_id(i,j)]=1;
}
}
bfs();
}
return 0;
}
C. 差值
只会 \(5\) 分。
由于取模之后就无法比较大小了,因此考虑把每位数用数组存下来。
枚举 \(len,l_1,l_2\),如果 \(f(l_1,l_1+len-1)<f(l_2,l_2+len-1)\) 则 swap(l1,l2)
,然后按照题目给定公式算出结果,并更新答案即可。比较就使用整数的比较法则即可,和十进制一样。
时间复杂度 \(O(n^4)\),枚举 \(O(n^3)\),更新答案 \(O(n)\)。
这个 sb 赛时认为代码是 \(O(n^3)\) 的,赛后没发现还怒斥 tlb 评测机垃圾()
代码:
#include<bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#define gt getchar
#define pt putchar
//typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 lll;
//typedef __uint128_t ulll;
const int N=1e6+5;
const int mod=1e9+7;
const int base=998244353;
using namespace std;
inline bool __(char ch){return ch>=48&&ch<=57;}
inline int read(){
int x=0;bool sgn=0;char ch=gt();
while(!__(ch)&&ch!=EOF) sgn|=(ch=='-'),ch=gt();
while(__(ch)) x=(x<<1)+(x<<3)+(ch&15),ch=gt();
return sgn?-x:x;
}
template<class T> inline void print(T x){
static char st[70];short top=0;
if(x<0)pt('-');
do{st[++top]=x>=0?(x%10+48):(-(x%10)+48),x/=10;}while(x);
while(top)pt(st[top--]);
}
template<class T> inline void printsp(T x){
print(x);
putchar(' ');
}
template<class T> inline void println(T x){
print(x);
putchar('\n');
}
inline void put_str(string s){
int siz=s.size();
for(int i=0;i<siz;++i) pt(s[i]);
printf("\n");
}
int n,a[N],b[N],ans[505][505];
inline void solve(int l1,int l2,int len){
bool cmp=1;
for(int i=0;i<len;++i){
if(a[l1+i]<a[l2+i]){
cmp=0;
break;
}
if(a[l1+i]>a[l2+i]) break;
}
if(!cmp) swap(l1,l2);
for(int i=0;i<len;++i) b[i]=a[l1+i]-a[l2+i];
cmp=0;
for(int i=0;i<len;++i){
if(b[i]<ans[len][i]){
cmp=1;
break;
}
if(b[i]>ans[len][i]) break;
}
if(cmp) for(int i=0;i<len;++i) ans[len][i]=b[i];
}
signed main(){
n=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int len=1;len<n;++len){
for(int i=0;i<len;++i) ans[len][i]=1e9;
for(int i=1;i<=n-len+1;++i){
for(int j=i+1;j<=n-len+1;++j){
solve(i,j,len);
}
}
}
for(int i=1;i<n;++i){
ll sum=0,ksm=1;
for(int j=i-1;j>=0;--j){
sum=(sum+ans[i][j]*ksm%mod)%mod;
sum=(sum%mod+mod)%mod;
ksm=(ksm*base)%mod;
}
printsp(sum);
}
return 0;
}
D. 基础循环结构练习题
首先考虑 \(b_i\) 递增时怎么做。
考虑一下取模操作的用途。经过思考,它可以起到消除最大值的作用。
这看似没什么用,但是它却可以帮助我们控制相邻两项的差。
举个例子,我们有 \(a\) 数组 \([1,2,3]\),然后我们进行以下操作:
-
全局对 \(3\) 取模,此时序列变为 \([1,2,0]\)。
-
全局加 \(x\),此时序列为 \([1+x,2+x,x]\)
-
全局对 \(2+x\) 取模,此时序列为 \([1+x,0,x]\)
这样我们就将 \(a_3-a_2\) 的值控制为了 \(x\)。
因此,我们只需要让 \(a_1=b_1\),然后保证对于任意 \(i\ge2\) \(a_i-a_{i-1}=b_i-b_{i-1}\) 即可。
具体地,我们记录 \(sum\) 表示全局加了多少。然后从 \(n\) 到 \(1\) 枚举 \(i\)(当前的最大值),全局对 \(sum+i\) 取模(使 \(a_i\) 变为 \(0\)),然后全局加上 \(b_i-b_{i-1}\)(控制差值),最后让 \(sum\) 加上 \(b_i-b_{i-1}\) 即可。
这样对于每个 \(i\) 都会进行两次操作。总操作次数 \(2n\),期望得分 \(35\) 分。
代码不写了。
实际上刚才的做法很具有启发性。我们考虑让 \(b\) 变成递增的:选取一个 \(>\max b_i\) 的值 \(B\),然后 \(b_i\to b_i+iS\),很明显此时序列是递增的。用相同的方法使得 \(a\) 变为此时的 \(b\) 序列,最后再对 \(B\) 全局取一次模即可。
总操作次数 \(2n+1\),期望得分 \(100\) 分。
这个算法的时间复杂度是 \(O(n)\) 的,所以 \(n\) 完全可以开到 \(10^7\)。可能这个数据范围单纯只是不想让答案爆掉 int
最后注意一下,\(B\) 应该比 \(b\) 的范围(\(10^5\))大,而不是 \(a\) 的范围(\(n\) 即 \(10^3\))!
代码:
#include<bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#define gt getchar
#define pt putchar
//typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 lll;
//typedef __uint128_t ulll;
const int N=1005;
const int B=1e5+5;
using namespace std;
inline bool __(char ch){return ch>=48&&ch<=57;}
inline int read(){
int x=0;bool sgn=0;char ch=gt();
while(!__(ch)&&ch!=EOF) sgn|=(ch=='-'),ch=gt();
while(__(ch)) x=(x<<1)+(x<<3)+(ch&15),ch=gt();
return sgn?-x:x;
}
template<class T> inline void print(T x){
static char st[70];short top=0;
if(x<0)pt('-');
do{st[++top]=x>=0?(x%10+48):(-(x%10)+48),x/=10;}while(x);
while(top) pt(st[top--]);
}
template<class T> inline void printsp(T x){
print(x);
putchar(' ');
}
template<class T> inline void println(T x){
print(x);
putchar('\n');
}
inline void put_str(string s){
int siz=s.size();
for(int i=0;i<siz;++i) pt(s[i]);
printf("\n");
}
int n,a[N],b[N];
signed main(){
n=read();
for(int i=1;i<=n;++i) a[i]=i,b[i]=read()+i*B;
println(2*n+1);
int sum=0;
for(int i=n;i;--i){
printf("2 %d\n",sum+i);
printf("1 %d\n",b[i]-b[i-1]);
sum+=(b[i]-b[i-1]);
}
printf("2 %d\n",B);
return 0;
}