解:首先看这个纯循环到底是什么玩意.....

经过一番打表,发现纯循环小数就是分母与进制互质的既约分数。

 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 循环之美相关推荐

  1. LOJ 2085: 洛谷 P1587: bzoj 4652: 「NOI2016」循环之美

    题目传送门:LOJ #2085. 两个月之前做的傻题,还是有必要补一下博客. 题意简述: 求分子为不超过 \(n\) 的正整数,分母为不超过 \(m\) 的正整数的所有互不相等的分数中,有多少在 \( ...

  2. 「NOI2016」循环之美 解题报告

    「NOI2016」循环之美 对于小数\(\frac{a}{b}\),如果它在\(k\)进制下被统计,需要满足要求并且不重复. 不重复我们确保这个分数是最简分数即\((a,b)=1\) 满足要求需要满足 ...

  3. *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 ...

  4. 【LOJ】#2085. 「NOI2016」循环之美

    题解 我们要求的其实是这个东西= = \(\sum_{i = 1}^{n}\sum_{j = 1}^{n}[(i,j) == 1][(j,k) == 1]\) 然后变一下形 \(\sum_{j = 1 ...

  5. [NOI2016]循环之美(杜教筛)

    首先要求每个数互不相等,故有$x\perp y$. 可以发现$\frac{x}{y}$在$k$进制下为纯循环小数的充要条件为$x\cdot k^{len}\equiv x(mod\ y)$,即$y\p ...

  6. 【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​中数值不同的纯循环小 ...

  7. 【NOI2016】循环之美,mobius反演+杜教筛

    思路: 对于xy\frac x y,我们肯定让gcd(x,y)=1\gcd(x,y)=1,因为这样计算不会重复,而且比不互质时更优,且只要余数出现重复就是有循环节了,根据十进制小数转k进制的方法,我们 ...

  8. Noi2016 循环之美

    题意相当于求如下式子 $$ \sum _{i=1}^{n} \sum_{j=1}^{m} [gcd(i,j)=1][gcd(j,k)=1] \\ k <= 1000 ; n,m <= 10 ...

  9. luogu P1587 [NOI2016] 循环之美

    https://www.luogu.com.cn/problem/P1587 首先思考我们要求的是什么? {xkly}={xy}\large \begin{Bmatrix}\frac{xk^l}{y} ...

最新文章

  1. shodan API 获取IP开放端口
  2. 干货|全面解析知识图谱:一种帮助通向强AI的数据科学技术
  3. WCF技术剖析之三十二:一步步创建一个完整的分布式事务应用
  4. mysql 单例模式好处_PHP单例模式的优点分析
  5. Linux 用户管理命令id、su
  6. Linux指令类型(一)change指令
  7. 通信行业力推零信任标准,蔷薇灵动微隔离首批获证
  8. 最简单的SpringMVC + Maven配置
  9. MonoTouch 二三事(三)mono mkbundle 打包程序的解包支持
  10. windows 7 局域网文件(夹)共享方法
  11. 《淘宝网开店 进货 运营 管理 客服 实战200招》——1.11 开店前要做好调查,预测市场...
  12. java me教程_Java ME基础教程
  13. SQL 删除重复数据,重复数据只保留ID最小的行
  14. Silverlight 4 Tools for Visual Studio 2010手动一步一步安装
  15. 60V降压芯片|60V转5V-12伏POE电源芯片
  16. [工具:iperf吞吐率测试工具 ]安装以及使用
  17. docker安装elasticsearch教程
  18. dos攻击的服务器修复,被dos攻击怎么解决
  19. Python数据处理工具——Pandas
  20. C++ 的 Copy Elision

热门文章

  1. 修复“-bash: locate: command not found”
  2. 沈阳建立通用航空产业基地,开辟国内首家无人机专用空域
  3. Spring Data JPA例子[基于Spring Boot、Mysql]
  4. rocketmq单机搭建
  5. gradle常用命令
  6. C#: .net序列化及反序列化 [XmlElement(“节点名称”)] [XmlAttribute(“节点属性”)] (上篇)...
  7. CodeForces 66C Petya and File System (实现)
  8. 使用Windows Live Writer发布日志
  9. 【查询】—Entity Framework实例详解
  10. 兼容低版本迅雷的js调用