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

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

 #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. 折腾Java设计模式之状态模式

    原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...

  2. Spring MVC(四)文件上传

    文件上传步骤 1.写一个文件上传的页面 2.写一个文件上传的控制器 注意: 1.method="post" 2.enctype="multipart/form-data& ...

  3. CSS中的一下小技巧1之CSS3三角形运用

    使用CSS3实现三角形: 在前端页面中有很多时候会遇到需要三角形图案的时候,以前不知道可以用CSS3实现三角形的时候,一般都是叫UI把三角形图案切出来. 后来知道原来可以用CSS3实现三角形,可是用过 ...

  4. ButterKnife 牛油刀使用

    一.butterknife介绍 ①官网 butterknife ②Field and method binding for Android Views which uses annotation pr ...

  5. Android视频录制从不入门到入门系列教程(二)————显示视频图像

    1.创建一个空的工程,注意声明下列权限: <uses-permission android:name="android.permission.CAMERA"/> < ...

  6. SQL 知道字段名 全表搜索此字段属于哪个表

    SELECT name FROM sysobjects WHERE id IN (SELECT ID FROM syscolumns WHERE name='字段名')

  7. NTFS权限和共享权限的区别

    共享权限 共享权限有三种:完全控制.更改.读取 共持本地安全性.换句话说,他在同一台计算机上以不同用户名登录,对硬盘上同一文件夹可以有不同的访问权限. 注意:NTFS权限对从网络访问和本机登录的用户都 ...

  8. apache环境下ssl证书链不完整问题解决,原因是缺少中间证书

    事情的起因是,对一个网站的升级,从http升级到https,苹果手机可以正常访问,唯独安卓手机出现空白,安卓访问https的时候是出现的空白. 服务器的系统是windows Server 2008 R ...

  9. 隐写术之steghide的使用

    steghide不是一个软件,所以下载之后解压缩就可以在命令行中使用. win+R,cmd,回车->进入到steghide.exe所在的文件夹,使用隐藏或者解锁的相应命令,即可隐藏或者解锁. 这 ...

  10. java 开发工具记录

    jenkins 持续构建项目 lombok  优雅代码插件 sonarqube 代码检测插件