[smoj 1022]位置

来源:互联网 发布:java二叉树非递归 编辑:程序博客网 时间:2024/05/22 02:05

题目描述

输入格式 1022.in

第一行:1个奇数N。
第二行:1个整数A。 (0 < A <= N*N)

输出格式 1022.out

一个整数,表示编号A地砖的位置编码。

输入样例 1022.in
5
20
输出样例 1022.out

28

数据范围:
80%数据 0 < N < 1000; 
100%数据 0 < N < 100000.

      数据量决定算法,先看数据量。80%数据0<N<1000;

                                                            100%数据0<N<100000;

     这题看题目时,想必很多同学都想到能用二维数组打表,然后再做吧,这样固然轻松,但一看数据量,集体懵比了。数组会爆掉的。

     只能刷八十分。

     所以,我们只能找规律了。

    而这题的规律也很好找,稍微画画图就想到了。

     

      我是第一次写博客画图,画的不好请多多包涵。

     画出上图之后,规律显而易见。我在此总结了三个规律:

     第一个规律是用来确定整数A是在第几层的,这是得出第三个规律的前提,不难发现每一层的最大数都是由上一层的最大数加上(这一层层数减1乘8的积)的。

     第二个规律,这是用来得出第一个规律的前提,1的横坐标是n÷2+1,纵坐标也是如此。

     第三个规律,得出每一层的第一个数,这也是最关键的一步,为了之后绕一圈求答案做铺垫。如图所示,每层的第一个数即是那一层最大的数(也就是最后一个数)-(这一层层数减1乘8的积)再加上1;

     有了这三个规律,我们就会发现,做这题变得简单多了,我们就可以完整地做出整道题(也就是正解了)。

     做法如下:

     1:首先依规律求出三个条件;

      2:接着开始从这一层的第一个数开始绕一圈,寻找这个数,最后找到这个熟后输出就行了。

      程序如下:

       

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;long long n,a,b,c,d,m,s=1,e,f,g=1;int main(){freopen("1022.in","r",stdin);freopen("1022.out","w",stdout);cin>>n>>m;a=n/2+1;//求一的坐标 b=n/2+1;//求一的坐标 if(m==1){cout<<a*n+b;return 0;}    long long i=1;    while(s<m)//算出整数A所在的层     {    c=c+8;    s=s+c;    i++;    }    d=i;     c=s-c+1;//整数A在的层的第一个数      e=a-d+1;//整数A在的层的第一个数的坐标      f=b-d+1;//整数A在的层的第一个数的坐标      g=d+d-2;//每次前进需要加的值       c=c+g;      // 绕一圈       if(c>=m)      {      f=f+(g-(c-m));      cout<<e*n+f;      return 0;      }      else      f=f+g;      c=c+g;      if(c>=m)      {      e=e+(g-(c-m));      cout<<e*n+f;      return 0;      }      else      e=e+g;      c=c+g;      if(c>=m)      {      f=f-(g-(c-m));      cout<<e*n+f;        return 0;  }      else        f=f-g;        c=c+g-1;        if(c>=m)        {        g=g-1;        e=e-(g-(c-m));        cout<<e*n+f;        return 0;        }return 0;}

0 0