首页 > 其他分享 >P1587 [NOI2016] 循环之美

P1587 [NOI2016] 循环之美

时间:2023-07-02 11:35:14浏览次数:48  
标签:10 return int sum 之美 mu NOI2016 P1587 define

题意

给定 \(n,m,k\) (\(1\le n,m\le10^9\),)问在 \(k\) 进制下有多少个分数值不同的 \(\frac{x}{y}\) 满足 \(x\le n,y\le m\) 且其小数形式的循环节从小数点后第一位开始。

sol

因为要求不同分数值,我们只考虑既约分数。类比十进制,故要求 \(gcd(y,k)=1\)。所以答案为:

\[\sum_{i=1}^{n}\sum_{j=1}^{m}[(i,j)=1][(j,k)=1] \]

很明显需要进一步化简:

\[\begin{aligned} &\sum_{i=1}^{n}\sum_{j=1}^{m}[(i,j)=1][(j,k)=1]\\ =&\sum_{i=1}^{n}\sum_{j=1}^{m}[(i,j)=1]\sum_{d|(j,k)}\mu(d)\\ =&\sum_{d|k}\mu(d)\sum_{i=1}^{n}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[(i,j)=1][(i,d)=1]\\ \end{aligned} \]

可以发现有一部分和原本的式子长得比较像,设原答案为 \(f(n,m,k)\),有

\[f(n,m,k)=\sum_{d|k}\mu(d)f(\lfloor\frac{m}{d}\rfloor,n, d) \]

可以递归求解,边界为 \(f(0,m,k)=f(n,0,k)=0\)。

\[\begin{aligned} f(n,m,1)=&\sum_{i=1}^{n}\sum_{j=1}^{m}[(i,j)=1]\\ =&\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{d|(i,j)}\mu(d)\\ =&\sum_{d=1}^{min(n,m)}\mu(d)\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor \end{aligned} \]

很经典的整除分块。但是这里 \(\mu\) 的前缀和要用到 \(10^9\) 所以使用杜教筛。

AC Code

#include <bits/stdc++.h>
namespace _default{
    using namespace std;
    #define lovely return
    #define _lzy_ 0
    #define LL long long
    #define DB double
    #define PII std::pair<int, int>
    #define X first
    #define Y second
    #define uF(i, x, y) for(int i = (x); i <= (y); ++ i)
    #define uf(i, x, y) for(int i = (x); i < (y); ++ i)
    #define dF(i, x, y) for(int i = (x); i >= (y); -- i)
    #define df(i, x, y) for(int i = (x); i > (y); -- i)
    #define ef(i, u) for(int i = head[(u)]; i; i = ne[i])
    #define sett(x, y) memset(x, y, sizeof x)
    #define copy(x, y) memcpy(x, y, sizeof x)
    const int MOD = 1e9 + 7, INF = 1e18;
    const DB EPS = 1e-8;
    template<typename T> inline T read(){
        T s = 0; int f = 0; char ch = getchar();
        while(!isdigit(ch)){if(ch == '-') f = 1; ch = getchar();}
        while(isdigit(ch)) s = s * 10 + ch - 48, ch = getchar();
        return f ? ~s + 1 : s;
    }
    template<typename T> inline void write(T x, const char *s = ""){
        static int st[40]; int top = 0;
        if(x < 0){putchar('-'); x = -x;}
        if(!x) putchar('0');
        while(x) st[++ top] = x % 10, x /= 10;
        while(top) putchar(st[top --] + 48);
        printf("%s", s);
    }
    template<typename T> inline void updmin(T &x, T y){if(x > y) x = y;}
    template<typename T> inline void updmax(T &x, T y){if(x < y) x = y;}
    template<typename T> inline void updadd(T &x, T y){(x += y % MOD) %= MOD;}
    template<typename T> inline void updmul(T &x, T y){(x *= y % MOD) %= MOD;}
    int cmp(DB a, DB b){if(fabs(a - b) < EPS) return 0; return a - b > EPS ? 1 : -1;}
}
using namespace _default;
const int N = 2005, M = 2e7;
int n, m, k;
int mu[M + 10], kk[M + 10], tot;
LL sm[M + 10];
bool Not_Prime[M + 10];
vector<int> p;
unordered_map<int, int> ttm;
struct lzy{
	int n, m, k;
	friend bool operator < (const lzy &a, const lzy &b){
		if(a.n != b.n) return a.n < b.n;
		else if(a.m != b.m) return a.m < b.m;
		else return a.k < b.k;
	}
};
map<lzy, LL> ans;
void xxs(){
	mu[1] = 1;
	uF(i, 2, M){
		if(!Not_Prime[i]){
			p.push_back(i);
			mu[i] = -1;
		}
		for(auto j : p){
			if(i * j > M) break;
			Not_Prime[i * j] = true;
			if(i % j == 0) break;
			mu[i * j] = -mu[i];
		}
	}
	uF(i, 1, M) sm[i] = sm[i - 1] + mu[i];
}
int getmu(int n){
    if(n <= M) return sm[n];
    if(ttm.count(n)) return ttm[n];
    LL res = 1;
    for(int l = 2, r; l <= n; l = r + 1){
        r = n / (n / l);
        res -= 1ll * (r - l + 1) * getmu(n / l);
    }
    return ttm[n] = res;
}
int Calc(int n, int m, int k){
	if(!n || !m) return 0;
	lzy tmp = (lzy){n, m, k};
	if(ans.count(tmp)) return ans[tmp];
	int res = 0;
	if(k == 1){
		int maxn = min(n, m);
		for(int l = 1, r; l <= maxn; l = r + 1){
			r = min(maxn, min(n / (n / l), m / (m / l)));
			res += (getmu(r) - getmu(l - 1)) * (n / l) * (m / l);
		}
		ans[(lzy){m, n, k}] = res;
	}
	else for(int i = 1; i <= tot && kk[i] <= k; ++ i) if(k % kk[i] == 0)
		res += Calc(m / kk[i], n, kk[i]) * mu[kk[i]];
	return ans[tmp] = res;
}
signed main(){
	n = read<int>(), m = read<int>(), k = read<int>();
	xxs();
	uF(i, 1, k) if(k % i == 0) kk[++ tot] = i;
	write(Calc(n, m, k));
    lovely _lzy_;
}

标签:10,return,int,sum,之美,mu,NOI2016,P1587,define
From: https://www.cnblogs.com/dks-and-xiao-yu/p/17520531.html

相关文章

  • 作者为何要写《简约之美》这本书?程序员们又能从中学到什么呢?
    好程序员和差程序员的区别在于理解能力。差劲的程序员不理解自己做的事情,优秀的程序员则相反。信不信由你,道理就是这么简单。写这本书,是为了帮助各位程序员,以适用于各种编程语言、各种项目的广阔视角来理解软件开发。本书以普通人容易理解的方式,讲解了软件开发的科学规律。如果......
  • 转:设计模式之美
    转自:https://juejin.cn/post/71230293553656627341.概述1.1学习导读本文是极客时间专栏《设计模式之美》的学习笔记,详情请看原文。学习算法:是为了写出高效的代码;学习设计模式:是为了写出高质量(可扩展、可读、可维护)的代码;1.2为什么学习设计模式应对面试,算法、设计......
  • 洛谷P1587 [NOI2016] 循环之美
    原文链接:[sol]P1587[NOI2016]循环之美-icyM3tra'sBlog此为备份。题目传送门0.前言提供一种式子较为简洁且不算难写的做法。以及介绍一种较为优秀的dp版杜教筛实现。1.式子推导我们知道纯循环小数一定可以写成分母形如\(k^a-1\)的分数。因此约分后的分母一定......
  • 后端编程之美
    如果你愿意去发现,那生活中处处都是美。同样,对于工作也是这样。只要你愿意,还是能发现一些乐趣的。作为一名后端开发工程师,我觉得后端编程的“美”在于:1、复杂且和谐:自己用代码构建的“元件”,配合已有的“元件”协同工作、达成目标。整个过程就像在搭建乐高。2、清晰且优美:每个类......
  • LeetCode 周赛 345(2023/05/14)体验一题多解的算法之美
    本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]提问。往期回顾:LeetCode双周赛第104场·流水的动态规划,铁打的结构化思考周赛概览T1.找出转圈游戏输家(Easy)标签:模拟、计数T2.相邻值的按位异或(Medium)标签:模拟、数学、构造T3.矩阵中移动的最......
  • luogu P4690 [Ynoi2016] 镜中的昆虫 题解
    P4690[Ynoi2016]镜中的昆虫题解题意维护一个长为 \(n\) 的序列 \(a_i\),有 \(m\) 次操作。将区间 \([l,r]\) 的值修改为 \(x\)。询问区间 \([l,r]\) 出现了多少种不同的数,也就是说同一个数出现多次只算一个。题解感觉这道题还是比较有意思的,像是一堆套路......
  • Java 编程之美总结
    内容来自王争Java编程之美1、Java基础1、程序本质:代码是如何被执行的?CPU、操作系统、虚拟机各司何职2、基础语法:从CPU角度看变量、数组、类型、运算、跳转、函数等语法3、引用类型:同样都是存储地址,为何Java引用比C/C++指针更安全4、基本类型:既然Java一切皆对......
  • 品味布隆过滤器的设计之美
    布隆过滤器是一个精巧而且经典的数据结构。你可能没想到:RocketMQ、Hbase、Cassandra、LevelDB、RocksDB这些知名项目中都有布隆过滤器的身影。对于后端程序员来讲,学习和理解布隆过滤器有很大的必要性。来吧,我们一起品味布隆过滤器的设计之美。1缓存穿透我们先来看一个......
  • P4688 [Ynoi2016] 掉进兔子洞
    RE了大约12次以后,SoN3ri告诉我是bitset开小了。那你为什么全RE了啊(?题意是给你一个长度为\(n\)的序列,一共\(m\)次询问,每次询问包含三个区间,求三个区间内相同的数去掉后剩下的数的个数。做完了小清新人渣的本愿,看啥都是bitset+莫队,这题我也是一开始打了一个莫队+bitset,但是......
  • 感受JavaLambda之美
    1Stream概述2Stream的创建3Stream的使用4Stream源码解读先贴上几个案例,水平高超的同学可以挑战一下:从员工集合中筛选出salary大于8000的员工,并放置到新的集合里。统计员工的最高薪资、平均薪资、薪资之和。将员工按薪资从高到低排序,同样薪资者年龄小者在前。将员......