LOJ#2085 循环之美
解:首先看这个纯循环到底是什么玩意.....
经过一番打表,发现纯循环小数就是分母与进制互质的既约分数。
1 #include <bits/stdc++.h> 2 3 std::bitset<1001> vis; 4 5 inline bool check(int x, int y) { /// x / y 6 //printf("x = %d y = %d \n", x, y); 7 vis.reset(); 8 int rest = x % y; 9 if(!rest) return true; 10 int op = rest; 11 vis[op] = 1; 12 //printf("op = %d \n", op); 13 while(true) { 14 rest *= 10; 15 int r = rest % y; 16 //printf("r = %d \n", r); 17 if(vis[r]) { 18 //printf("return %d = %d \n", r, op); 19 return r == op; 20 } 21 vis[r] = 1; 22 rest = r; 23 } 24 return false; 25 } 26 27 int gcd(int a, int b) { 28 if(!b) return a; 29 return gcd(b, a % b); 30 } 31 32 int main() { 33 34 int n; 35 scanf("%d", &n); 36 37 for(int i = 0; i <= n; i++) { 38 for(int j = 1; j <= n; j++) { 39 if(gcd(i, j) == 1) printf("%d ", (int)check(i, j)); 40 else printf(" "); 41 } 42 puts(""); 43 } 44 45 return 0; 46 }
打表程序
那么就有了一个很显然的O(nmlogV)的做法...直接暴力枚举然后检验。实测24分。
1 #include <bits/stdc++.h> 2 3 int gcd(int a, int b) { 4 if(!b) return a; 5 return gcd(b, a % b); 6 } 7 8 int main() { 9 int n, m, k, ans = 0; 10 scanf("%d%d%d", &n, &m, &k); 11 if(1ll * n * m > 1000000000) return 0; 12 for(int i = 1; i <= m; i++) { 13 if(gcd(k, i) > 1) continue; 14 for(int j = 1; j <= n; j++) { 15 ans += gcd(i, j) == 1; 16 } 17 } 18 printf("%d\n", ans); 19 return 0; 20 }
24分暴力
然后发现最里面那句话有点像phi...仔细思考之后发现不是。
现在开始鬼畜时间...推柿子。
其中有两步转化,分别是把[x=1]用∑μ代替和把[1=(id,k)]用[1=(i,k)][1=(d,k)]代替。
于是考虑最后这个式子,发现有个东西[1=(a,k)],于是设这个东西为g(x),它的前缀和为f(x)。又令F为μ·g的前缀和。
那么答案就是下式:
这个东西显然可以分块一波。后两项可以O(1)算,前面的可以线性预处理。于是我们有个O(n)的算法。可以获得84分。
1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 const int N = 20000010; 5 6 int miu[N], p[N], top, f[N], phi[N], n, m, k, F[N]; 7 bool vis[N]; 8 9 inline void getp(int n) { 10 phi[1] = miu[1] = 1; 11 for(int i = 2; i <= n; i++) { 12 if(!vis[i]) { 13 p[++top] = i; 14 miu[i] = -1; 15 phi[i] = i - 1; 16 } 17 for(int j = 1; j <= top && i * p[j] <= n; j++) { 18 vis[i * p[j]] = 1; 19 if(i % p[j] == 0) { 20 //miu[i * p[j]] = 0; 21 phi[i * p[j]] = phi[i] * p[j]; 22 break; 23 } 24 phi[i * p[j]] = phi[i] * (p[j] - 1); 25 miu[i * p[j]] = -miu[i]; 26 } 27 } 28 return; 29 } 30 31 int gcd(int a, int b) { 32 if(!b) return a; 33 return gcd(b, a % b); 34 } 35 36 inline void prework() { 37 for(int i = 1; i <= k; i++) { 38 f[i] = f[i - 1] + (gcd(i, k) == 1); 39 F[i] = F[i - 1] + (f[i] - f[i - 1]) * miu[i]; 40 } 41 int len = std::min(n, m); 42 for(int i = k + 1; i <= len; i++) { 43 f[i] = f[k] * (i / k) + f[i % k]; 44 F[i] = F[i - 1] + (f[i] - f[i - 1]) * miu[i]; 45 } 46 return; 47 } 48 49 inline int getf(int x) { 50 if(x <= k) return f[x]; 51 return f[k] * (x / k) + f[x % k]; 52 } 53 54 int main() { 55 LL ans = 0; 56 scanf("%d%d%d", &n, &m, &k); 57 if(1ll * n * m < 1e9) { 58 for(int i = 1; i <= m; i++) { 59 if(gcd(k, i) > 1) continue; 60 for(int j = 1; j <= n; j++) { 61 ans += gcd(i, j) == 1; 62 } 63 } 64 printf("%lld\n", ans); 65 return 0; 66 } 67 if(n < N) { 68 getp(n); 69 prework(); 70 int len = std::min(n, m); 71 for(int i = 1, j; i <= len; i = j + 1) { 72 j = std::min(n / (n / i), m / (m / i)); 73 /// [i, j] 74 ans += 1ll * (F[j] - F[i - 1]) * (n / i) * getf(m / i); 75 } 76 printf("%lld\n", ans); 77 } 78 return 0; 79 }
84分代码
接下来补个k = 2 / 3的部分分。严格来说应该能应付k是质数的情况,然而后面k都是合数....
推倒过程几乎跟上面一样,最后得到这个东西:
考虑怎么计算后面那个求和符号。当d和k不互质(d是k的倍数)的时候,答案显然是0。否则令t = i / d,答案就是与k互质的t个个数。这个东西我们可以用maxt - maxt / k来O(1)计算。
1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 const int N = 20000010; 5 6 int miu[N], p[N], top, f[N], phi[N], n, m, k, F[N]; 7 bool vis[N]; 8 9 inline void getp(int n) { 10 phi[1] = miu[1] = 1; 11 for(int i = 2; i <= n; i++) { 12 if(!vis[i]) { 13 p[++top] = i; 14 miu[i] = -1; 15 phi[i] = i - 1; 16 } 17 for(int j = 1; j <= top && i * p[j] <= n; j++) { 18 vis[i * p[j]] = 1; 19 if(i % p[j] == 0) { 20 //miu[i * p[j]] = 0; 21 phi[i * p[j]] = phi[i] * p[j]; 22 break; 23 } 24 phi[i * p[j]] = phi[i] * (p[j] - 1); 25 miu[i * p[j]] = -miu[i]; 26 } 27 } 28 return; 29 } 30 31 int gcd(int a, int b) { 32 if(!b) return a; 33 return gcd(b, a % b); 34 } 35 36 inline int calc(int d) { 37 if((d % k) == 0) { 38 return 0; 39 } 40 d = m / d; 41 return d - d / k; 42 } 43 44 inline void prework() { 45 for(int i = 1; i <= k; i++) { 46 f[i] = f[i - 1] + (gcd(i, k) == 1); 47 F[i] = F[i - 1] + (f[i] - f[i - 1]) * miu[i]; 48 } 49 int len = std::min(n, m); 50 for(int i = k + 1; i <= len; i++) { 51 f[i] = f[k] * (i / k) + f[i % k]; 52 F[i] = F[i - 1] + (f[i] - f[i - 1]) * miu[i]; 53 } 54 return; 55 } 56 57 inline int getf(int x) { 58 if(x <= k) return f[x]; 59 return f[k] * (x / k) + f[x % k]; 60 } 61 62 int main() { 63 LL ans = 0; 64 scanf("%d%d%d", &n, &m, &k); 65 if(1ll * n * m < 1e9) { 66 for(int i = 1; i <= m; i++) { 67 if(gcd(k, i) > 1) continue; 68 for(int j = 1; j <= n; j++) { 69 ans += gcd(i, j) == 1; 70 } 71 } 72 printf("%lld\n", ans); 73 return 0; 74 } 75 if((k == 2 || k == 3) && (n <= 10000)) { 76 getp(n); 77 int len = std::min(n, m); 78 for(int i = 1; i <= len; i++) { 79 ans += 1ll * miu[i] * (n / i) * calc(i); 80 } 81 printf("%lld\n", ans); 82 return 0; 83 } 84 /*if(n < N) { 85 getp(n); 86 prework(); 87 int len = std::min(n, m); 88 for(int i = 1, j; i <= len; i = j + 1) { 89 j = std::min(n / (n / i), m / (m / i)); 90 /// [i, j] 91 ans += 1ll * (F[j] - F[i - 1]) * (n / i) * getf(m / i); 92 } 93 printf("%lld\n", ans); 94 }*/ 95 return 0; 96 }
40分代码
转载于:https://www.cnblogs.com/huyufeifei/p/10760649.html
LOJ#2085 循环之美相关推荐
- LOJ 2085: 洛谷 P1587: bzoj 4652: 「NOI2016」循环之美
题目传送门:LOJ #2085. 两个月之前做的傻题,还是有必要补一下博客. 题意简述: 求分子为不超过 \(n\) 的正整数,分母为不超过 \(m\) 的正整数的所有互不相等的分数中,有多少在 \( ...
- 「NOI2016」循环之美 解题报告
「NOI2016」循环之美 对于小数\(\frac{a}{b}\),如果它在\(k\)进制下被统计,需要满足要求并且不重复. 不重复我们确保这个分数是最简分数即\((a,b)=1\) 满足要求需要满足 ...
- *LOJ#2085. 「NOI2016」循环之美
$n \leq 1e9,m \leq 1e9,k \leq 2000$,求$k$进制下$\frac{x}{y}$有多少种不同的纯循环数取值,$1 \leq x \leq n,1 \leq y \leq ...
- 【LOJ】#2085. 「NOI2016」循环之美
题解 我们要求的其实是这个东西= = \(\sum_{i = 1}^{n}\sum_{j = 1}^{n}[(i,j) == 1][(j,k) == 1]\) 然后变一下形 \(\sum_{j = 1 ...
- [NOI2016]循环之美(杜教筛)
首先要求每个数互不相等,故有$x\perp y$. 可以发现$\frac{x}{y}$在$k$进制下为纯循环小数的充要条件为$x\cdot k^{len}\equiv x(mod\ y)$,即$y\p ...
- 【NOI2016】循环之美【莫比乌斯反演】【整除分块】【杜教筛】【类杜教筛】
传送门 题意:给定n,m,kn,m,kn,m,k,求1≤x≤n,1≤y≤m1\leq x\leq n,1\leq y\leq m1≤x≤n,1≤y≤m时xyx \over yyx中数值不同的纯循环小 ...
- 【NOI2016】循环之美,mobius反演+杜教筛
思路: 对于xy\frac x y,我们肯定让gcd(x,y)=1\gcd(x,y)=1,因为这样计算不会重复,而且比不互质时更优,且只要余数出现重复就是有循环节了,根据十进制小数转k进制的方法,我们 ...
- Noi2016 循环之美
题意相当于求如下式子 $$ \sum _{i=1}^{n} \sum_{j=1}^{m} [gcd(i,j)=1][gcd(j,k)=1] \\ k <= 1000 ; n,m <= 10 ...
- luogu P1587 [NOI2016] 循环之美
https://www.luogu.com.cn/problem/P1587 首先思考我们要求的是什么? {xkly}={xy}\large \begin{Bmatrix}\frac{xk^l}{y} ...
最新文章
- shodan API 获取IP开放端口
- 干货|全面解析知识图谱:一种帮助通向强AI的数据科学技术
- WCF技术剖析之三十二:一步步创建一个完整的分布式事务应用
- mysql 单例模式好处_PHP单例模式的优点分析
- Linux 用户管理命令id、su
- Linux指令类型(一)change指令
- 通信行业力推零信任标准,蔷薇灵动微隔离首批获证
- 最简单的SpringMVC + Maven配置
- MonoTouch 二三事(三)mono mkbundle 打包程序的解包支持
- windows 7 局域网文件(夹)共享方法
- 《淘宝网开店 进货 运营 管理 客服 实战200招》——1.11 开店前要做好调查,预测市场...
- java me教程_Java ME基础教程
- SQL 删除重复数据,重复数据只保留ID最小的行
- Silverlight 4 Tools for Visual Studio 2010手动一步一步安装
- 60V降压芯片|60V转5V-12伏POE电源芯片
- [工具:iperf吞吐率测试工具 ]安装以及使用
- docker安装elasticsearch教程
- dos攻击的服务器修复,被dos攻击怎么解决
- Python数据处理工具——Pandas
- C++ 的 Copy Elision
热门文章
- 修复“-bash: locate: command not found”
- 沈阳建立通用航空产业基地,开辟国内首家无人机专用空域
- Spring Data JPA例子[基于Spring Boot、Mysql]
- rocketmq单机搭建
- gradle常用命令
- C#: .net序列化及反序列化 [XmlElement(“节点名称”)] [XmlAttribute(“节点属性”)] (上篇)...
- CodeForces 66C 	Petya and File System (实现)
- 使用Windows Live Writer发布日志
- 【查询】—Entity Framework实例详解
- 兼容低版本迅雷的js调用