【USACO】ariprog
输入 : N M
要找到长度为 N 的等差数列,要求数列中每个数字都可以表达成 a^2 + b^2 的和, 数字大小不超过M^2 + M^2
输出: 等差数列首元素 间隔 (多组答案分行输出)
解题思路:因为等差数列的数字都是平房和数 所以先生成所有的 从0 - M^2 + M^2的平方和数 去掉相同的并从小到大排序
然后对 所有间隔 、 首元素 做循环 判断能否找到以该首元素和间隔为条件的其他N-1个需要的数字 可以就存成答案;
提交后超时了.... test 5的时候 超了5s 正在想简化办法 超时的代码
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #define MAXN 200000
- int 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 = ; i < binum - ; i++)
- {
- gap[i] = bisquare[i + ] - bisquare[i];
- }
- //..................
- //if(find(bisquare, binum, bisquare[j] + k * i) == 0)
- //{
- // flag = 0;
- // break;
- //}
- int inter = ;
- while(inter < i && m <= binum - )
- {
- inter = inter + gap[m];
- m++;
- }
- if(inter != i)
- {
- flag = ;
- 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) / ;
- int aa= T[m];
- if(T[m] == x)
- {
- return ;
- }
- else if(T[m] < x)
- {
- l = m + ;
- }
- else
- {
- r = m - ;
- }
- }
- if(T[l] == x)
- {
- return ;
- }
- return ;
- }
---------------------------------------------------------
用了个及其NC的优化办法 把间隔循环的上限设到 3000 , 首元素循环上限设到 第10000个元素 算是半个作弊了.... 代码主要就是在这两个地方耗时间。间隔循环是 M^2数量级个,首元素binum是(M+1)^2的量级。这两个一嵌套就是M^4 不知道用什么规则化简, 只好强制设上限了。 AC代码
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #define MAXN 200000
- int 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) / ;
- int aa= T[m];
- if(T[m] == x)
- {
- return ;
- }
- else if(T[m] < x)
- {
- l = m + ;
- }
- else
- {
- r = m - ;
- }
- }
- if(T[l] == x)
- {
- return ;
- }
- return ;
- }
- int main()
- {
- FILE *in, *out;
- in = fopen("ariprog.in", "r");
- out = fopen("ariprog.out", "w");
- int bisquare[]; //存储所有可以用的平方数
- int binum = ; //存储可用平方数的个数
- int ans[][];
- int anum = ; //答案个数
- int M, N;
- int i, j, k;
- for(i = ; i < ; i++)
- {
- bisquare[i] = MAXN;
- }
- fscanf(in, "%d %d", &N, &M);
- for(i = ; i <= M; i++)
- {
- for(j = ; j <= M; j++)
- {
- bisquare[binum] = i * i + j * j;
- binum++;
- }
- }
- qsort(bisquare, binum, sizeof(bisquare[]), cmp);
- //去掉相同的平方和数
- int numt = binum;
- for(i = ; i < numt; i++)
- {
- if(bisquare[i] == bisquare[i + ])
- {
- bisquare[i] = MAXN;
- binum--;
- }
- }
- qsort(bisquare, numt, sizeof(bisquare[]), cmp);
- int flag;
- //对所有间隔大小, 所有起始位搜索
- for(i = ; i <= /*M * M * 2*/; i++)
- {
- for(j = ; j < && j < binum - N + ; j++)
- {
- flag = ;
- int m = j;
- for(k = ; k < N; k++)
- {
- if(BinarySearch(bisquare, j + , binum - , bisquare[j] + k * i) == )
- {
- flag = ;
- break;
- }
- }
- if(flag == )
- {
- ans[anum][] = bisquare[j];
- ans[anum][] = i;
- anum++;
- }
- }
- }
- if(anum > )
- {
- for(i = ; i < anum; i++)
- {
- fprintf(out, "%d %d\n", ans[i][], ans[i][]);
- }
- }
- else
- {
- fprintf(out, "NONE\n");
- }
- return ;
- }
----------------------------------
看了答案 用了一种更NB的查找方法 直接建一个0,1大数组 有该数设为1 没有设为0 直接读取即可 改为这种常数时间的查找后 时间又是呈数量级式的下降了
间隔的上限为 M * M * 2 / (N - 1) 首元素的循环条件为 bisquare[j] + (N - 1) * 当前间隔 <= M * M * 2 整体修改后 计算时间均在2s以内
最终版完整代码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #define MAXN 200000
- int 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) / ;
- int aa= T[m];
- if(T[m] == x)
- {
- return ;
- }
- else if(T[m] < x)
- {
- l = m + ;
- }
- else
- {
- r = m - ;
- }
- }
- if(T[l] == x)
- {
- return ;
- }
- return ;
- }
- int main()
- {
- FILE *in, *out;
- in = fopen("ariprog.in", "r");
- out = fopen("ariprog.out", "w");
- int bisquare[]; //存储所有可以用的平方数
- int binum = ; //存储可用平方数的个数
- int ans[][];
- int is[] = {};
- int anum = ; //答案个数
- int M, N;
- int i, j, k;
- for(i = ; i < ; i++)
- {
- bisquare[i] = MAXN;
- }
- fscanf(in, "%d %d", &N, &M);
- for(i = ; i <= M; i++)
- {
- for(j = ; j <= M; j++)
- {
- if(is[i * i + j * j] == ) //用is判断可以去掉重复的数字
- {
- bisquare[binum] = i * i + j * j;
- binum++;
- is[i * i + j * j] = ;
- }
- }
- }
- qsort(bisquare, binum, sizeof(bisquare[]), cmp);
- int flag;
- int upperb = M * M * / (N - );
- //对所有间隔大小, 所有起始位搜索
- for(i = ; i <= upperb; i++)
- {
- for(j = ; bisquare[j] + (N - ) * i <= M * M * ; j++)
- {
- flag = ;
- int m = j;
- for(k = ; k < N; k++)
- {
- if(is[bisquare[j] + k * i] == )
- {
- flag = ;
- break;
- }
- }
- if(flag == )
- {
- ans[anum][] = bisquare[j];
- ans[anum][] = i;
- anum++;
- }
- }
- }
- if(anum > )
- {
- for(i = ; i < anum; i++)
- {
- fprintf(out, "%d %d\n", ans[i][], ans[i][]);
- }
- }
- else
- {
- fprintf(out, "NONE\n");
- }
- return ;
- }
【USACO】ariprog的更多相关文章
- POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 【USACO】距离咨询(最近公共祖先)
POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 [USACO]距离咨询(最近公共祖先) Description F ...
- 1642: 【USACO】Payback(还债)
1642: [USACO]Payback(还债) 时间限制: 1 Sec 内存限制: 64 MB 提交: 190 解决: 95 [提交] [状态] [讨论版] [命题人:外部导入] 题目描述 &quo ...
- 1519: 【USACO】超级书架
1519: [USACO]超级书架 时间限制: 1 Sec 内存限制: 64 MB 提交: 1735 解决: 891 [提交] [状态] [讨论版] [命题人:外部导入] 题目描述 Farmer Jo ...
- Java实现【USACO】1.1.2 贪婪的礼物送礼者 Greedy Gift Givers
[USACO]1.1.2 贪婪的礼物送礼者 Greedy Gift Givers 题目描述 对于一群要互送礼物的朋友,你要确定每个人送出的礼物比收到的多多少(and vice versa for th ...
- 【CPLUSOJ】【USACO】【差分约束】排队(layout)
[题目描述] Robin喜欢将他的奶牛们排成一队.假设他有N头奶牛,编号为1至N.这些奶牛按照编号大小排列,并且由于它们都很想早点吃饭,于是就很可能出现多头奶牛挤在同一位置的情况(也就是说,如果我们认 ...
- 【USACO】Dining
[题目链接] [JZXX]点击打开链接 [caioj]点击打开链接 [算法] 拆点+网络流 [代码] #include<bits/stdc++.h> using namespace std ...
- 【USACO】Optimal Milking
题目链接 : [POJ]点击打开链接 [caioj]点击打开链接 算法 : 1:跑一遍弗洛伊德,求出点与点之间的最短路径 2:二分答案,二分”最大值最小“ 3.1:建边,将 ...
- 【USACO】 Balanced Photo
[题目链接] 点击打开链接 [算法] 树状数组 [代码] #include<bits/stdc++.h> using namespace std; int i,N,ans,l1,l2; ] ...
- 【USACO】 Balanced Lineup
[题目链接] 点击打开链接 [算法] 这是一道经典的最值查询(RMQ)问题. 我们首先想到线段树.但有没有更快的方法呢?对于这类问题,我们可以用ST表(稀疏表)算法求解. 稀疏表算法.其实也是一种动态 ...
随机推荐
- 蝙蝠算法-python实现
BAIndividual.py import numpy as np import ObjFunction class BAIndividual: ''' individual of bat algo ...
- BZOJ3229 石子合并
Description 在一个操场上摆放着一排N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分. 试设计一个算法,计算出将N堆石 ...
- Linux X Window System运行原理和启动过程
本文主要说明X Window System的基本运行原理,其启动过程,及常见的跨网络运行X Window System. 一) 基本运行原理 X Window System采用C/S结构,但和我们常见 ...
- POJ1328Radar Installation(区间点覆盖问题)
Radar Installation Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 68597 Accepted: 15 ...
- UIScrollview自动布局,UIScrollviewAutolayoutDemo
参考文档:http://www.cocoachina.com/ios/20150104/10810.html UIScrollviewAutolayoutDemo地址:http://pan.baidu ...
- 我在 impress.js 中学到的小套路
我在 impress.js 中学到的小套路 写在开篇 作为了一个自学 JavaScript 才一个月的新手,前几天“妄图”研究 jQuery-3.1.0 源码,结果自然是被虐得死去活来.机缘巧合之下, ...
- DEDECMS全版本gotopage变量XSS ROOTKIT 0DAY
影响版本: DEDECMS全版本 漏洞描叙: DEDECMS后台登陆模板中的gotopage变量未效验传入数据,导致XSS漏洞. \dede\templets\login.htm 65行左右 < ...
- struts2拦截器interceptor的三种配置方法
1.struts2拦截器interceptor的三种配置方法 方法1. 普通配置法 <struts> <package name="struts2" extend ...
- cocos进阶教程(2)多分辨率支持策略和原理
cocos2d-x3.0API常用接口 Director::getInstance()->getOpenGLView()->setDesignResolutionSize() //设计分辨 ...
- PPTP服务器配置选项详解
导读 PPTP服务器配置文件的格式与其它许多Unix程序相似,每一行包含一项配置内容,以配置选项名称开始,后面紧跟参数值或者关键字,它们之间用空格分隔.在读取配置文件时,pptpd进程将忽略空行和每一 ...