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

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

 #include <bits/stdc++.h>

 std::bitset<> vis;

 inline bool check(int x, int y) { /// x / y
//printf("x = %d y = %d \n", x, y);
vis.reset();
int rest = x % y;
if(!rest) return true;
int op = rest;
vis[op] = ;
//printf("op = %d \n", op);
while(true) {
rest *= ;
int r = rest % y;
//printf("r = %d \n", r);
if(vis[r]) {
//printf("return %d = %d \n", r, op);
return r == op;
}
vis[r] = ;
rest = r;
}
return false;
} int gcd(int a, int b) {
if(!b) return a;
return gcd(b, a % b);
} int main() { int n;
scanf("%d", &n); for(int i = ; i <= n; i++) {
for(int j = ; j <= n; j++) {
if(gcd(i, j) == ) printf("%d ", (int)check(i, j));
else printf(" ");
}
puts("");
} return ;
}

打表程序

那么就有了一个很显然的O(nmlogV)的做法...直接暴力枚举然后检验。实测24分。

 #include <bits/stdc++.h>

 int gcd(int a, int b) {
if(!b) return a;
return gcd(b, a % b);
} int main() {
int n, m, k, ans = ;
scanf("%d%d%d", &n, &m, &k);
if(1ll * n * m > ) return ;
for(int i = ; i <= m; i++) {
if(gcd(k, i) > ) continue;
for(int j = ; j <= n; j++) {
ans += gcd(i, j) == ;
}
}
printf("%d\n", ans);
return ;
}

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分。

 #include <bits/stdc++.h>

 typedef long long LL;
const int N = ; int miu[N], p[N], top, f[N], phi[N], n, m, k, F[N];
bool vis[N]; inline void getp(int n) {
phi[] = miu[] = ;
for(int i = ; i <= n; i++) {
if(!vis[i]) {
p[++top] = i;
miu[i] = -;
phi[i] = i - ;
}
for(int j = ; j <= top && i * p[j] <= n; j++) {
vis[i * p[j]] = ;
if(i % p[j] == ) {
//miu[i * p[j]] = 0;
phi[i * p[j]] = phi[i] * p[j];
break;
}
phi[i * p[j]] = phi[i] * (p[j] - );
miu[i * p[j]] = -miu[i];
}
}
return;
} int gcd(int a, int b) {
if(!b) return a;
return gcd(b, a % b);
} inline void prework() {
for(int i = ; i <= k; i++) {
f[i] = f[i - ] + (gcd(i, k) == );
F[i] = F[i - ] + (f[i] - f[i - ]) * miu[i];
}
int len = std::min(n, m);
for(int i = k + ; i <= len; i++) {
f[i] = f[k] * (i / k) + f[i % k];
F[i] = F[i - ] + (f[i] - f[i - ]) * miu[i];
}
return;
} inline int getf(int x) {
if(x <= k) return f[x];
return f[k] * (x / k) + f[x % k];
} int main() {
LL ans = ;
scanf("%d%d%d", &n, &m, &k);
if(1ll * n * m < 1e9) {
for(int i = ; i <= m; i++) {
if(gcd(k, i) > ) continue;
for(int j = ; j <= n; j++) {
ans += gcd(i, j) == ;
}
}
printf("%lld\n", ans);
return ;
}
if(n < N) {
getp(n);
prework();
int len = std::min(n, m);
for(int i = , j; i <= len; i = j + ) {
j = std::min(n / (n / i), m / (m / i));
/// [i, j]
ans += 1ll * (F[j] - F[i - ]) * (n / i) * getf(m / i);
}
printf("%lld\n", ans);
}
return ;
}

84分代码

接下来补个k = 2 / 3的部分分。严格来说应该能应付k是质数的情况,然而后面k都是合数....

推倒过程几乎跟上面一样,最后得到这个东西:

考虑怎么计算后面那个求和符号。当d和k不互质(d是k的倍数)的时候,答案显然是0。否则令t = i / d,答案就是与k互质的t个个数。这个东西我们可以用maxt - maxt / k来O(1)计算。

 #include <bits/stdc++.h>

 typedef long long LL;
const int N = ; int miu[N], p[N], top, f[N], phi[N], n, m, k, F[N];
bool vis[N]; inline void getp(int n) {
phi[] = miu[] = ;
for(int i = ; i <= n; i++) {
if(!vis[i]) {
p[++top] = i;
miu[i] = -;
phi[i] = i - ;
}
for(int j = ; j <= top && i * p[j] <= n; j++) {
vis[i * p[j]] = ;
if(i % p[j] == ) {
//miu[i * p[j]] = 0;
phi[i * p[j]] = phi[i] * p[j];
break;
}
phi[i * p[j]] = phi[i] * (p[j] - );
miu[i * p[j]] = -miu[i];
}
}
return;
} int gcd(int a, int b) {
if(!b) return a;
return gcd(b, a % b);
} inline int calc(int d) {
if((d % k) == ) {
return ;
}
d = m / d;
return d - d / k;
} inline void prework() {
for(int i = ; i <= k; i++) {
f[i] = f[i - ] + (gcd(i, k) == );
F[i] = F[i - ] + (f[i] - f[i - ]) * miu[i];
}
int len = std::min(n, m);
for(int i = k + ; i <= len; i++) {
f[i] = f[k] * (i / k) + f[i % k];
F[i] = F[i - ] + (f[i] - f[i - ]) * miu[i];
}
return;
} inline int getf(int x) {
if(x <= k) return f[x];
return f[k] * (x / k) + f[x % k];
} int main() {
LL ans = ;
scanf("%d%d%d", &n, &m, &k);
if(1ll * n * m < 1e9) {
for(int i = ; i <= m; i++) {
if(gcd(k, i) > ) continue;
for(int j = ; j <= n; j++) {
ans += gcd(i, j) == ;
}
}
printf("%lld\n", ans);
return ;
}
if((k == || k == ) && (n <= )) {
getp(n);
int len = std::min(n, m);
for(int i = ; i <= len; i++) {
ans += 1ll * miu[i] * (n / i) * calc(i);
}
printf("%lld\n", ans);
return ;
}
/*if(n < N) {
getp(n);
prework();
int len = std::min(n, m);
for(int i = 1, j; i <= len; i = j + 1) {
j = std::min(n / (n / i), m / (m / i));
/// [i, j]
ans += 1ll * (F[j] - F[i - 1]) * (n / i) * getf(m / i);
}
printf("%lld\n", ans);
}*/
return ;
}

40分代码

LOJ#2085 循环之美的更多相关文章

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

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

  2. UOJ #221 【NOI2016】 循环之美

    题目链接:循环之美 这道题感觉非常优美--能有一个这么优美的题面和较高的思维难度真的不容易-- 为了表示方便,让我先讲一下两个符号.\([a]\)表示如果\(a\)为真,那么返回\(1\),否则返回\ ...

  3. 【BZOJ4652】【NOI2016】循环之美(莫比乌斯反演,杜教筛)

    [BZOJ4652]循环之美(莫比乌斯反演,杜教筛) 题解 到底在求什么呢... 首先不管他\(K\)进制的问题啦,真是烦死啦 所以,相当于有一个分数\(\frac{i}{j}\) 因为值要不相等 所 ...

  4. LibreOJ2085 - 「NOI2016」循环之美

    Portal Description 给出\(n,m(n,m\leq10^9)\)和\(k(k\leq2000)\),求在\(k\)进制下,有多少个数值不同的纯循环小数可以表示成\(\dfrac{x} ...

  5. [UOJ#221][BZOJ4652][Noi2016]循环之美

    [UOJ#221][BZOJ4652][Noi2016]循环之美 试题描述 牛牛是一个热爱算法设计的高中生.在他设计的算法中,常常会使用带小数的数进行计算.牛牛认为,如果在 k 进制下,一个数的小数部 ...

  6. 「NOI2016」循环之美

    P1587 [NOI2016]循环之美 题目描述 牛牛是一个热爱算法设计的高中生.在他设计的算法中,常常会使用带小数的数进行计算.牛牛认为,如果在 $k$ 进制下,一个数的小数部分是纯循环的,那么它就 ...

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

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

  8. luogu 1587 [NOI2016]循环之美

    LINK:NOI2016循环之美 这道题是 给出n m k 求出\(1\leq i\leq n,1\leq j\leq m\) \(\frac{i}{j}\)在k进制下是一个纯循环的. 由于数值相同的 ...

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

随机推荐

  1. IntelliJ IDEA如何激活?

    本文使用的IDEA的版本是:14.0.3 下载IDEA授权服务器(下载地址见最后),并解压,打开解压后的IntelliJIDEALicenseServer目录,可以看到如下的两个文件: Intelli ...

  2. 山西大同大学教务处学生端--送给学弟,学妹的礼物,可在PC端,手机端操作

    解决问题:大同大学教务处官网学生端口一进去就卡住了,点上面一行的菜单无响应 转眼已是四年,想想自己大学即将结束,不由得让人感慨啊.这才刚开学几天,我就听到有同学在因为补考,选课的事情发愁.学校官方的教 ...

  3. springboot集成elasticsearch

    在基础阶段学习ES一般是首先是 安装ES后借助 Kibana 来进行CURD 了解ES的使用: 在进阶阶段可以需要学习ES的底层原理,如何通过Version来实现乐观锁保证ES不出问题等核心原理: 第 ...

  4. appium+python搭建自动化测试框架_TestAPP框架(三)

    Pycharm 创建 Project,搭建 APPTEST框架如下图:   1.框架功能 业务功能的封装 测试用例封装 测试包管理 截图处理 断言处理 日志获取 测试报告生成 数据驱动 数据配置 2. ...

  5. 【English】十四、英语

    一.英语 是 词法(词) + 语法 一个个拥有词法的词,就是材料.通过语法的规则将这些词合理组合排列起来.然后,就可以干很多事了.

  6. Node.js安装及环境配置之Windows篇---完美,win7已测

    一.安装环境 1.本机系统:Windows 10 Pro(64位) (楼主win7,完美通过)2.Node.js:v6.9.2LTS(64位) (楼主版本2018-11-01下载的最新版本) 二.安装 ...

  7. thinkphp5.1验证器场景验证中传参的方法。

    一个场景:用户保存自己的昵称,如果已经有其他用户用了这个昵称则不允许保存,但是要排除当前用户自己,因为如果用户未作修改,新昵称和老昵称一样,是可以保存的. 因为昵称定义了唯一规则: 'name' =& ...

  8. sqlserver数据库NULL类型注意事项

    1,变量NULL类型赋值需要初始化 2,判断条件

  9. zabbix利用SNMPTrap接收交换机主动告警

    zabbix接收trap的工作流程: snmptrapd 收到trap snmptrapd将trap传递给SNMPTT或调用Perl接收器 SNMPTT或Perl trap接收器解析,格式化并将tra ...

  10. centos修改默认启动级别

    Linux分为7个启动级别: 0 - 系统停机状态 1 - 单用户工作状态 2 - 多用户状态(没有NFS) 3 - 多用户状态(有NFS) 4 - 系统未使用,留给用户 5 - 图形界面 6 - 系 ...