P2550 [AHOI2001]彩票摇奖和P2615 [NOIP2015 提高组] 神奇的幻方(洛谷oj)

P2550 [AHOI2001]彩票摇奖
题目描述:
P2550 [AHOI2001]彩票摇奖和P2615 [NOIP2015 提高组] 神奇的幻方(洛谷oj)_第1张图片
P2550 [AHOI2001]彩票摇奖和P2615 [NOIP2015 提高组] 神奇的幻方(洛谷oj)_第2张图片
思路:这道题思路很简单,就是先让你输入一个固定的中奖号码,再输入n行彩票号码(即小明买了n张彩票),将每行彩票号码与中奖号码进行比对,记录彩票号码中出现的中奖号码数字的次数,比如例子12 8 9 23 1 16 7与中奖号码23 31 1 14 19 17 18比对,出现了23和1这两个数字,根据题目要求该号码获得了五等奖,即在输出数组中的a[5]处加1,表示中了一次五等奖;同理,11 7 10 21 2 9 31中只有中奖号码数字31出现了1次,根据题目该号码获得了六等奖,即在对应输出数组中的a[6]处加1,表示中了一次六等奖。
题目分析到这里,我说一说我在这道题上踩的坑,首先我看到题目最后测试数据规模为1<=n<1000,就鬼使神差地把数组范围设成了1000多,实际上这道题完全不需要那么大的数组,这个n代表的是我们循环的次数,与数组本身无关,在进行数据比较操作的时候实际上只是那7个数字进行比较,所以我们只需要设置一个长度为7的存储中奖号码的a数组,和一个长度一样为7的最后输出的中奖数组flag。这个程序的核心实际上是一个while循环嵌套一个两层的for循环(实现比较),这道题就AC了。
上代码:

#include
#include
using namespace std;
int a[7];
int flag[7];
int main(){
int n;
int m;
while(scanf("%d",&n)!=EOF){
        //中奖号码
    int cnt = 0;
    //这里为了保险,我把flag数组初始化为0
    memset(flag,0,sizeof(flag));
    //输入我们的中奖数组
    for(int i = 0;i<7;i++){
        scanf("%d",&a[i]);
    }
   //买了n张彩票,循环进行n次
    while(n--){
        for(int i = 0;i<7;i++){
        //依次输入数据,单个处理
            scanf("%d",&m);
            for(int j = 0;j<7;j++){
                if(m==a[j]){
                //记录次数
                    cnt++;
                }
            }
        }
        //在对应的中奖数组上加1
        flag[7-cnt]++;
        //对cnt重置清零
        cnt = 0;
    }
    //最后输出打印
    for(int i = 0;i<7;i++){
        printf("%d ",flag[i]);
    }
    printf("\n");
}


return 0;
}

2.[NOIP2015 提高组] 神奇的幻方
题目描述:
P2550 [AHOI2001]彩票摇奖和P2615 [NOIP2015 提高组] 神奇的幻方(洛谷oj)_第3张图片
题目很冗长,我在做的时候没有耐心看,就直接去搜了什么是奇数幻方,读者可以去这位博主的博客详细了解奇数阶幻方构造法
幻方确实是一个非常有意思的数学问题,确实很神奇,实际上读懂了这篇博客,这道题也就迎刃而解。我想分享一下我解决这道题的心得,我最开始做的时候,是直接按位置来进行模拟它不断叠加,实际上这是我们人脑的惯有思路,虽然肯定是能做得出来的,但中间确实有很多逻辑上的错误,本人亲身体验过。对于这道题,我们最好还是以解迷宫题一样的思路,把开始初始的这个1看做是一个小人,让他一直往右上方走,如果走出迷宫(二维数组)了,在把他按照幻方构造的要求给扯回来,这么一想,我就觉得这道题就不是之前那么有点不好理解了。上代码:

//奇数幻方问题
#include
using namespace std;
const int maxn = 45;
int a[maxn][maxn];
int main()
{
  int n;
  int i,j;
  while(scanf("%d",&n)!=EOF){
     i = 0;
     j = n/2;
     //赋初始值
     a[0][n/2] = 1;
     int sum  = 1;
     while(sum<=n*n){
        a[i][j] = sum;
        //如果sum是n的倍数
        if(sum%n==0){
           //向下走一步
            i++;
            //如果走到了下边界
          if(i==n){
              i = 0;//重新置为第一行
          }
        }else{
            //往右上角走一步
           i--;
           j++;
        }
        //两种走到了边界的情况
        if(i==-1)i = n - 1;
        if(j== n)j = 0;
        sum++;//一直不断进行叠加
     }
    //最后输出打印
    for(int i = 0;i<n;i++){
        for(int j = 0;j<n;j++){
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }


  }
    return 0;
}

你可能感兴趣的:(洛谷刷题)