Farey Polygon
2015-08-02 19:02
561 查看
题目描述:
先给出一个法雷序列:在法雷序列之前加上0/0;F1 = {0⁄0, 0⁄1, 1⁄1}
F2 = {0⁄0, 0⁄1, 1⁄2, 1⁄1}
F3 = {0⁄0, 0⁄1, 1⁄3, 1⁄2, 2⁄3, 1⁄1}
F4 = {0⁄0, 0⁄1, 1⁄4, 1⁄3, 1⁄2, 2⁄3, 3⁄4, 1⁄1}
F5 = {0⁄0, 0⁄1, 1⁄5, 1⁄4, 1⁄3, 2⁄5, 1⁄2, 3⁄5, 2⁄3, 3⁄4, 4⁄5, 1⁄1}
F6 = {0⁄0, 0⁄1, 1⁄6, 1⁄5, 1⁄4, 1⁄3, 2⁄5, 1⁄2, 3⁄5, 2⁄3, 3⁄4, 4⁄5, 5⁄6, 1⁄1}
F7 = {0⁄0, 0⁄1, 1⁄7, 1⁄6, 1⁄5, 1⁄4, 2⁄7, 1⁄3, 2⁄5, 3⁄7, 1⁄2, 4⁄7, 3⁄5, 2⁄3, 5⁄7, 3⁄4, 4⁄5, 5⁄6, 6⁄7, 1⁄1}
F8 = {0⁄0, 0⁄1, 1⁄8, 1⁄7, 1⁄6, 1⁄5, 1⁄4, 2⁄7, 1⁄3, 3⁄8, 2⁄5, 3⁄7, 1⁄2, 4⁄7, 3⁄5, 5⁄8, 2⁄3, 5⁄7, 3⁄4, 4⁄5, 5⁄6, 6⁄7, 7⁄8, 1⁄1}
然后将这些序列按照顺序映射到二维的坐标上.
分子是y,分母是x.按照顺序将他们连在一起,最后一个连第一个点.
然后这个图形里面就严格包含了一些点.
有一个倍率放大是m.就是把每一个点都放大.
现在给出严格包含了多少个点,要求给出满足的(n,m).n尽量小,n一样的话m尽量小.
12000组数据,要求n和m都<=15000,还没找到的话就是-1.
具体题意:http://acm.bnu.edu.cn/v3/problem_show.php?pid=20856
题解:
首先格子内部的点是有一个定理:在二维的方格中,围成的面积S = I(内部) + (V(边上)/2) - 1; 我们知道的是I(内部).其次观察面积和边上点的性质.既然给出的是一个奇怪的序列.这个序列我们第一反应是可以用phi前缀和求出它的个数.那么我们猜想S和V是否只和点的个数有关.发现还真是:V = m*(点个数), S = (点个数-2)/2;
知道了这些,我们写出公式,发现m有二次方,那么我们暴力枚举m,然后可以得到需要的phi,这一点非常重要,因为得到phi中有一个需要整除的过程,能够特别快的加速计算.然后二分查找phi.
重点:
(1)知道算内部的公式.(2)利用phi好求个数来猜想
(3)求phi是利用整除.
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <ctype.h> #include <limits.h> #include <cstdlib> #include <algorithm> #include <vector> #include <queue> #include <map> #include <stack> #include <set> #include <bitset> #define CLR(a) memset(a, 0, sizeof(a)) #define REP(i, a, b) for(ll i = a;i < b;i++) #define REP_D(i, a, b) for(ll i = a;i <= b;i++) typedef long long ll; using namespace std; const ll maxn = 15001 + 10; const ll key = 15000; ll phi[maxn]; ll p[maxn], pn, vis[maxn]; void getPhi() { CLR(vis); phi[1] = 1; pn = 0; for(ll i = 2; i<=key; i++) { if(!vis[i]) { phi[i] = i-1; p[pn] = i; pn++; } for(ll j = 0; (j<pn&&i*p[j]<=key); j++) { if(i%p[j]) { phi[i*p[j]] = phi[i]*(p[j]-1); vis[i*p[j]] = 1; } else { phi[i*p[j]] = phi[i]*(p[j]); vis[i*p[j]] = 1; } } } for(int i = 2; i<=key; i++) { phi[i] += phi[i-1]; } } ll n, m; ll ans; void solve() { for(m = key; m>=2; m--) { ll X = (2*ans+2*m-2); ll Y = (m*m-m); if(X%Y==0)//这一点是关键.不然要T { X /= Y; ll pos = lower_bound(phi + 1, phi + 1+key, X) - phi; if(pos != (key + 1) && phi[pos] == X) { printf("%lld %lld\n", pos, m); return; } } } printf("NOT FOUND\n"); } int main() { // freopen("13Min.txt", "r", stdin); //freopen("1out.txt", "w", stdout); getPhi(); while(scanf("%lld", &ans)) { if(ans==-1) { break; } if(ans == 0) { printf("1 1\n"); } else solve(); } return 0; }
相关文章推荐
- Django学习(一)
- Algorithm --> KMP算法
- Dragon Balls HDU杭电3635 【并查集,递归的方法找根节点】
- django notes 三:Template 的查找
- Good Luck in CET-4 Everybody! HDOJ(巴什博弈)
- hdoj 3635 Dragon Balls【并查集】
- codeforces 559A A. Gerald's Hexagon(几何题)
- Google黑客常用的入侵语法
- HDU 3635 Dragon Balls 带权并查集
- django notes 二:URL dispatcher
- django notes 一:开篇
- Google Play Store启用AdWords搜索广告
- poj 2762 Going from u to v or from v to u? 【判断图是否为弱连通】 【tarjan求SCC + 缩点 + 拓扑排序】
- HackerRank - "Lego Blocks"
- Django新手需要注意的10个要点
- django环境搭建
- django book学习笔记――模板
- 第三方应用如何调用google maps导航或显示某个区域的地图
- category、protocol、delegate总结
- Dragon Balls