• USACO 1.4 ariprog 解题报告


      这是继虫洞之后又让我为难的一个 剪枝题目,无论如何,做的再快,也只能过6个点,最后三个点也TLE。后来参考了一下标答,大概思路是这样的。

      朴素算法就不多说了,枚举a,b然后判断就行,网上说这样优化到位的话,是可能过掉的,但是我一直没有优化出来,所以就放弃了这一做法。。

      标答的做法:首先要预处理一下所有的双平方数,我的做法是只用BOOL标记,但是这里还要存一下数的序列。然后,我们知道,我们要找的等差数列中的第一个数一定是这里面的数,那么就利用这一个特点,每次从公差开始枚举,如果序列长度还不够,但是已经超过了限制,或者根本就不是序列中的数,就标记一下,如果这个标记在判断的时候没有被标记过,说明这组解是可行的,就保存下来。。。写到这里才发现这题好水好水。

      没有自己A掉这题的根本原因是因为没有深入思考这数的性质,话说一开始我理解这题也是读了上十遍,最后没明白请教的别人题意,最关键的一句话:我们要找的等差数列中的第一个数一定是这个序列里面的数。。。

      下面直接代码。

     1     #include <iostream>
     2     #include <cstdlib>
     3     #include <cstring>
     4     #include <cstdio>
     5     #include <algorithm>
     6      
     7     using namespace std;
     8      
     9     int N,M;
    10      
    11     int tot = 0,size = 0;
    12     bool vi[125001];
    13     int list[125001];
    14      
    15     int i,j,k;
    16      
    17     struct data{
    18         int a,b;
    19     }ans[10000];
    20      
    21     bool cmp(data,data);
    22      
    23     int main(){
    24         freopen("ariprog.in","r",stdin);
    25         freopen("ariprog.out","w",stdout);
    26         scanf("%d%d",&N,&M);
    27         for(i = 0;i <= M;++ i)
    28             for(j = 0;j <= M;++ j){
    29                 vi[i*i + j*j] = true;
    30             }
    31         for(i = 0;i <= 2*M*M;++ i){
    32             if(vi[i])
    33                 list[++ tot] = i;
    34         }
    35         
    36         for(i = 1;i <= tot;++ i){
    37             for(j = i+1;j <= tot;++ j){
    38                 int tp = list[j] - list[i];
    39                 bool flag = false;
    40                 for(k = 2;k < N;++ k){
    41                     if(list[i]+tp*k > 2*M*M || !vi[list[i]+tp*k]){
    42                         flag = true;
    43                         break;
    44                     }
    45                 }
    46                 if(!flag){
    47                     size ++;
    48                     ans[size].a = list[i];
    49                     ans[size].b = tp;
    50                 }
    51             }
    52         }
    53         if(size){
    54             sort(ans+1,ans+size+1,cmp);
    55             for(i = 1;i <= size;++ i)
    56                 printf("%d %d
    ",ans[i].a,ans[i].b);
    57         }
    58         else{
    59             printf("NONE
    ");
    60         }
    61         return 0;
    62     }
    63      
    64     bool cmp(data a,data b){
    65         if(a.b == b.b)
    66             return a.a < b.a;
    67         else
    68             return a.b < b.b;
    69     }
    View Code

      做完这题后,又看了一下下一节的第一题,数字三角形,主要是滚动数组的用法。。

      dp[i&1][j] = ....dp[1-(i&1)][j...]乱搞。。。。。

  • 相关阅读:
    面试题汇总--1
    行内元素与块级元素
    前端面试题整理---JS基础
    springmvc处理一个请求的全流程
    反射+动态代理+类加载+JVM
    json注解及序列化
    加密
    Thread setUncaughtExceptionHandler
    RunTime.getRunTime().addShutdownHook 添加钩子
    MySQL日志
  • 原文地址:https://www.cnblogs.com/sxprovence/p/4709040.html
Copyright © 2020-2023  润新知