博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【USACO】ariprog
阅读量:5834 次
发布时间:2019-06-18

本文共 8118 字,大约阅读时间需要 27 分钟。

输入 : N  M

要找到长度为 N 的等差数列,要求数列中每个数字都可以表达成 a^2 + b^2 的和, 数字大小不超过M^2 + M^2 

输出: 等差数列首元素 间隔 (多组答案分行输出)

 

解题思路:因为等差数列的数字都是平房和数  所以先生成所有的 从0 - M^2 + M^2的平方和数 去掉相同的并从小到大排序

然后对 所有间隔 、 首元素 做循环 判断能否找到以该首元素和间隔为条件的其他N-1个需要的数字 可以就存成答案;

 

提交后超时了.... test 5的时候 超了5s 正在想简化办法 超时的代码

 

#include 
#include
#include
#define MAXN 200000int cmp(const void *va, const void *vb){ return (*(int *)va) - (*(int *)vb);}int find(int * bisquare, int binum, int num){ int i; for(i = 0; i < binum; i++) { if(bisquare[i] == num) return 1; } return 0;}int main(){ FILE *in, *out; in = fopen("ariprog.in", "r"); out = fopen("ariprog.out", "w"); int bisquare[40000]; //存储所有可以用的平方数 int binum = 0; //存储可用平方数的个数 int ans[10000][2]; int anum = 0; //答案个数 int gap[25]; //存储间隔 int M, N; int i, j, k; for(i = 0; i < 40000; i++) { bisquare[i] = MAXN; } fscanf(in, "%d %d", &N, &M); for(i = 0; i <= M; i++) { for(j = 0; j <= M; j++) { bisquare[binum] = i * i + j * j; binum++; } } qsort(bisquare, binum, sizeof(bisquare[0]), cmp); //去掉相同的平方和数 int numt = binum; for(i = 0; i < numt; i++) { if(bisquare[i] == bisquare[i + 1]) { bisquare[i] = MAXN; binum--; } } qsort(bisquare, numt, sizeof(bisquare[0]), cmp); int flag; //对所有间隔大小, 所有起始位搜索 for(i = 1; i <= M * M * 2; i++) { for(j = 0; j < binum - N + 1; j++) { flag = 1; for(k = 1; k < N; k++) { if(find(bisquare, binum, bisquare[j] + k * i) == 0) { flag = 0; break; } } if(flag == 1) { ans[anum][0] = bisquare[j]; ans[anum][1] = i; anum++; } } } if(anum > 0) { for(i = 0; i < anum; i++) { fprintf(out, "%d %d\n", ans[i][0], ans[i][1]); } } else { fprintf(out, "NONE\n"); } return 0;}

 

----------------

对于查找的办法做了化简 之前用find函数一个一个的比较 但实际上 我们只需要搜索与当前首元素右侧相邻的一些数字, 若发现搜索的数字与当前首元素的差值已经大于n个间隔了 则返回查找失败

方法:存储相邻两个数之间的差值, 从当前首元素开始对差值求和,求和值不能大于间隔

修改的部分代码:

for(i = 0; i < binum - 1; i++)    {        gap[i] = bisquare[i + 1] - bisquare[i];    }//..................                //if(find(bisquare, binum, bisquare[j] + k * i) == 0)                //{                //    flag = 0;                //    break;                //}                int inter = 0;                while(inter < i && m <= binum - 1)                {                    inter = inter + gap[m];                    m++;                }                if(inter != i)                {                    flag = 0;                    break;                }//....................

修改后 test5 通过了 但test6 还是超时了.... 还要继续化简

----------------------

继续对查找过程优化 用目前最快的二分查找 O(logn) 的 查找范围是首元素之后的元素 真的是数量级的变快了 test5从 4s+ 变到了 0.389s 只是test 6 仍然超时了... 在自己电脑上跑了一下 差不多10s的样子会出来结果 也比之前的查找快多了  果然,学了就要用啊........    查找的算法见下面  还需要继续优化

int BinarySearch(int * T, int left, int right, int x){        int l = left, r = right;    while(l < r)    {        int m = (l + r) / 2;        int aa= T[m];        if(T[m] == x)        {            return 1;        }        else if(T[m] < x)        {            l = m + 1;        }        else        {            r = m - 1;        }    }    if(T[l] == x)    {        return 1;    }    return 0;}

 ---------------------------------------------------------

用了个及其NC的优化办法  把间隔循环的上限设到 3000  , 首元素循环上限设到 第10000个元素  算是半个作弊了.... 代码主要就是在这两个地方耗时间。间隔循环是 M^2数量级个,首元素binum是(M+1)^2的量级。这两个一嵌套就是M^4  不知道用什么规则化简, 只好强制设上限了。 AC代码

#include 
#include
#include
#define MAXN 200000int cmp(const void *va, const void *vb){ return (*(int *)va) - (*(int *)vb);}int BinarySearch(int * T, int left, int right, int x){ int l = left, r = right; while(l < r) { int m = (l + r) / 2; int aa= T[m]; if(T[m] == x) { return 1; } else if(T[m] < x) { l = m + 1; } else { r = m - 1; } } if(T[l] == x) { return 1; } return 0;}int main(){ FILE *in, *out; in = fopen("ariprog.in", "r"); out = fopen("ariprog.out", "w"); int bisquare[70000]; //存储所有可以用的平方数 int binum = 0; //存储可用平方数的个数 int ans[10000][2]; int anum = 0; //答案个数 int M, N; int i, j, k; for(i = 0; i < 40000; i++) { bisquare[i] = MAXN; } fscanf(in, "%d %d", &N, &M); for(i = 0; i <= M; i++) { for(j = 0; j <= M; j++) { bisquare[binum] = i * i + j * j; binum++; } } qsort(bisquare, binum, sizeof(bisquare[0]), cmp); //去掉相同的平方和数 int numt = binum; for(i = 0; i < numt; i++) { if(bisquare[i] == bisquare[i + 1]) { bisquare[i] = MAXN; binum--; } } qsort(bisquare, numt, sizeof(bisquare[0]), cmp); int flag; //对所有间隔大小, 所有起始位搜索 for(i = 1; i <= /*M * M * 2*/3000; i++) { for(j = 0; j < 10000 && j < binum - N + 1; j++) { flag = 1; int m = j; for(k = 1; k < N; k++) { if(BinarySearch(bisquare, j + 1, binum - 1, bisquare[j] + k * i) == 0) { flag = 0; break; } } if(flag == 1) { ans[anum][0] = bisquare[j]; ans[anum][1] = i; anum++; } } } if(anum > 0) { for(i = 0; i < anum; i++) { fprintf(out, "%d %d\n", ans[i][0], ans[i][1]); } } else { fprintf(out, "NONE\n"); } return 0;}

 

 ----------------------------------

看了答案  用了一种更NB的查找方法  直接建一个0,1大数组 有该数设为1 没有设为0 直接读取即可 改为这种常数时间的查找后 时间又是呈数量级式的下降了  

间隔的上限为 M * M * 2 / (N - 1)   首元素的循环条件为 bisquare[j] + (N - 1) * 当前间隔 <= M * M * 2 整体修改后 计算时间均在2s以内

最终版完整代码:

#include 
#include
#include
#define MAXN 200000int cmp(const void *va, const void *vb){ return (*(int *)va) - (*(int *)vb);}int BinarySearch(int * T, int left, int right, int x){ int l = left, r = right; while(l < r) { int m = (l + r) / 2; int aa= T[m]; if(T[m] == x) { return 1; } else if(T[m] < x) { l = m + 1; } else { r = m - 1; } } if(T[l] == x) { return 1; } return 0;}int main(){ FILE *in, *out; in = fopen("ariprog.in", "r"); out = fopen("ariprog.out", "w"); int bisquare[70000]; //存储所有可以用的平方数 int binum = 0; //存储可用平方数的个数 int ans[10000][2]; int is[125001] = {
0}; int anum = 0; //答案个数 int M, N; int i, j, k; for(i = 0; i < 70000; i++) { bisquare[i] = MAXN; } fscanf(in, "%d %d", &N, &M); for(i = 0; i <= M; i++) { for(j = 0; j <= M; j++) { if(is[i * i + j * j] == 0) //用is判断可以去掉重复的数字 { bisquare[binum] = i * i + j * j; binum++; is[i * i + j * j] = 1; } } } qsort(bisquare, binum, sizeof(bisquare[0]), cmp); int flag; int upperb = M * M * 2 / (N - 1); //对所有间隔大小, 所有起始位搜索 for(i = 1; i <= upperb; i++) { for(j = 0; bisquare[j] + (N - 1) * i <= M * M * 2; j++) { flag = 1; int m = j; for(k = 1; k < N; k++) { if(is[bisquare[j] + k * i] == 0) { flag = 0; break; } } if(flag == 1) { ans[anum][0] = bisquare[j]; ans[anum][1] = i; anum++; } } } if(anum > 0) { for(i = 0; i < anum; i++) { fprintf(out, "%d %d\n", ans[i][0], ans[i][1]); } } else { fprintf(out, "NONE\n"); } return 0;}

 

转载地址:http://xzucx.baihongyu.com/

你可能感兴趣的文章
ASMFD (ASM Filter Driver) Support on OS Platforms (Certification Matrix). (文档 ID 2034681.1)
查看>>
CRM Transaction处理中的权限控制
查看>>
[转]linux创建链接文件的两种方法
查看>>
python ipaddress模块使用
查看>>
文件权限
查看>>
busybox里的僵尸进程为何那么多
查看>>
python debug
查看>>
java 连接数据库之一个完整的函数
查看>>
mysql脚本
查看>>
OllyDBG 入门系列教学--让你瞬间成为破解高手
查看>>
Dubbo点滴(2)之集群容错
查看>>
检测不到兼容的键盘驱动程序
查看>>
listbox用法
查看>>
冲刺第九天 1.10 THU
查看>>
传值方式:ajax技术和普通传值方式
查看>>
Linux-网络连接-(VMware与CentOS)
查看>>
寻找链表相交节点
查看>>
AS3——禁止swf缩放
查看>>
linq 学习笔记之 Linq基本子句
查看>>
[Js]布局转换
查看>>