bjfu1211 推公式,筛素数
题目是求fun(n)的值
fun(n)= Gcd(3)+Gcd(4)+…+Gcd(i)+…+Gcd(n).
Gcd(n)=gcd(C[n][1],C[n][2],……,C[n][n-1])
C[n][k] means the number of way to choose k things from n things.
n最大一百万,马上反映到可能是递推打表。
首先肯定是推公式了,fun(n)其实就是Gcd(n)的一个前n项和,没意义,直接看Gcd(n),把前几项列出来,发现公式是Gcd(n) = lcm(1,……,n-1,n)/lcm(1,……,n-1),其中lcm是求若干个数的最小公倍数。例如Gcd(1)=lcm(1)=1, Gcd(2)=lcm(1,2)/lcm(1)=2,
Gcd(6)=lcm(1,2,3,4,5,6)/lcm(1,2,3,4,5)=60/60=1
于是我马上想到了方法,先筛法打出一百万以内的素数表,然后从lcm(1,2)开始逐个往后递推lcm(1,……,n-1,n),开一个数组来表示其值(数组每一位表示某个素数,值表示这个素因子的个数)。但是这样的话,递推的时候必须遍历素数表,就算只考虑1000以内的素数,也超过100个,很有可能超时。
不过因为是学弟出的题,本着测试的态度,我按这个思路打了一个,果然超时,看来数据不算太水。
/*
* Author : ben
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <functional>
#include <numeric>
#include <cctype>
using namespace std; #ifdef ON_LOCAL_DEBUG
#else
#endif
typedef long long LL;
const int MAXN = ;
LL ans[MAXN];
int pn, pt[MAXN], num[MAXN];
bool ip[MAXN];
int N = ;
void init_prime_table() {
memset(ip, true, sizeof(ip));
int i;
ip[] = false;
pn = ;
pt[pn++] = ;
for (i = ; i < N; i += ) {
ip[i] = false;
}
for (i = ; i * i <= N; i += ) {
if (!ip[i])
continue;
pt[pn++] = i;
for (int s = * i, j = i * i; j < N; j += s)
ip[j] = false;
}
for (; i < N; i++) {
if (ip[i]) {
pt[pn++] = i;
}
}
}
inline int mypow(int a, int b) {
int ret = ;
while (b--) {
ret *= a;
}
return ret;
} int comput() {
ans[] = ;
for (int i = ; i <= N; i++) {
if (ip[i]) {
num[i]++;
ans[i] = i;
continue;
}
int _gcd = ;
int n = i;
for (int j = ; j < pn; j++) {
if (n == ) {
break;
}
if (n > && ip[n]) {
break;
}
int t = ;
while (n % pt[j] == ) {
t++;
n = n / pt[j];
}
if (t > num[pt[j]]) {
_gcd *= mypow(pt[j], t - num[pt[j]]);
num[pt[j]] = t;
}
}
ans[i] = _gcd;
}
for (int i = ; i < MAXN; i++) {
ans[i] += ans[i - ];
}
return ;
} int main() {
#ifdef ON_LOCAL_DEBUG
freopen("data.in", "r", stdin);
#endif
int n;
// get_prime_table(MAXN);
init_prime_table();
// pn = pt.size();
memset(num, , sizeof(num));
comput();
while (scanf("%d", &n) == ) {
printf("%I64d\n", ans[n]);
}
return ;
}
下面是正解。正解的方法对上面那种方法的改进类似于筛法对普通求素数法的改进。原来的方法这么工作:比如在递推到n=8的时候,发现8有三个素因子2,而之前的lcm里只有两个素因子2,所以这次的值会再乘一个2。那么新方法直接倒过来,当递推到2的时候,发现2是素数,那么就把2^2,2^3,2^4等等的ans里都预先乘上一个2。这样就避免了遍历素数表,降低了复杂度,而且代码更为简洁。代码如下:
/*
* Author : ben
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <functional>
#include <numeric>
#include <cctype>
using namespace std; #ifdef ON_LOCAL_DEBUG
#else
#endif
typedef long long LL;
const int MAXN = ;
LL ans[MAXN];
int pn, pt[MAXN];
bool ip[MAXN];
int N = MAXN;
void init_prime_table() {
memset(ip, true, sizeof(ip));
int i;
ip[] = false;
pn = ;
pt[pn++] = ;
for (i = ; i < N; i += ) {
ip[i] = false;
}
for (i = ; i * i <= N; i += ) {
if (!ip[i])
continue;
pt[pn++] = i;
for (int s = * i, j = i * i; j < N; j += s)
ip[j] = false;
}
for (; i < N; i++) {
if (ip[i]) {
pt[pn++] = i;
}
}
} int comput() {
fill(ans, ans + N + , );
for (int i = ; i <= N; i++) {
if (ip[i]) {
LL t = i;
while (t <= N) {
ans[t] *= i;
t *= i;
}
}
}
for (int i = ; i < MAXN; i++) {
ans[i] += ans[i - ];
}
return ;
} int main() {
#ifdef ON_LOCAL_DEBUG
// freopen("test.in", "r", stdin);
// freopen("data.out", "w", stdout);
freopen("data.in", "r", stdin);
#endif
int n;
init_prime_table();
comput();
while (scanf("%d", &n) == ) {
printf("%I64d\n", ans[n]);
}
return ;
}
bjfu1211 推公式,筛素数的更多相关文章
- 【板子】gcd、exgcd、乘法逆元、快速幂、快速乘、筛素数、快速求逆元、组合数
1.gcd int gcd(int a,int b){ return b?gcd(b,a%b):a; } 2.扩展gcd )extend great common divisor ll exgcd(l ...
- ACM-ICPC 2018 南京赛区网络预赛 J题Sum(线性筛素数)
题目链接:https://nanti.jisuanke.com/t/30999 参考自博客:https://kuangbin.github.io/2018/09/01/2018-ACM-ICPC-Na ...
- codeforces 185A Plant(推公式)
Plant [题目链接]Plant [题目类型]推公式 &题解: 这个是可以推公式的: 每年的总个数是4^n个,设n年时向上的个数是x个,向下的个数是y个,那么n+1年时,向上的个数是3* x ...
- 欧拉函数O(sqrt(n))与欧拉线性筛素数O(n)总结
欧拉函数: 对正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目. POJ 2407.Relatives-欧拉函数 代码O(sqrt(n)): ll euler(ll n){ ll ans=n; ...
- 全网一定不是最好懂的C++线性筛素数
Part 0:概念 先给几个概念(很重要): 合数:如果\(xy=z\text{且}x,y\text{为正整数}\),我们就说\(x,y\text{是}z\text{的合数}\) 素数:如果数\(a\ ...
- CF449C Jzzhu and Apples (筛素数 数论?
Codeforces Round #257 (Div. 1) C Codeforces Round #257 (Div. 1) E CF450E C. Jzzhu and Apples time li ...
- HDU 4873 ZCC Loves Intersection(JAVA、大数、推公式)
在一个D维空间,只有整点,点的每个维度的值是0~n-1 .现每秒生成D条线段,第i条线段与第i维度的轴平行.问D条线段的相交期望. 生成线段[a1,a2]的方法(假设该线段为第i条,即与第i维度的轴平 ...
- HDU 4870 Rating(概率、期望、推公式) && ZOJ 3415 Zhou Yu
其实zoj 3415不是应该叫Yu Zhou吗...碰到ZOJ 3415之后用了第二个参考网址的方法去求通项,然后这次碰到4870不会搞.参考了chanme的,然后重新把周瑜跟排名都反复推导(不是推倒 ...
- 洛谷P3383 【模板】线性筛素数
P3383 [模板]线性筛素数 256通过 579提交 题目提供者HansBug 标签 难度普及- 提交 讨论 题解 最新讨论 Too many or Too few lines 样例解释有问题 ...
随机推荐
- REST_FRAMEWORK加深记忆-加了用户登陆认证,自定义权限的API接口
哈哈,终于快结束了.. urls.py from django.conf.urls import include, url from django.contrib import admin urlpa ...
- C Primer Plus之高级数据表示
抽象数据类型(ADT) 类型是由什么组成?一个类型(type)指定两类信息:一个属性集和一个操作集. 所以您想定义一个新的数据类型.首先,您需要提供存储数据的方式,可能是通过设计一个结构.第二 ...
- python 字符串格式化 输出
1. 需要输出3列,为了输出好看,需要制定每一列的宽度: ‘%6.2f’ % 1.235 # 长度为6,保留2为小数 print '{0:20} {1:<20} {1:<20}\r\n'. ...
- XE2编译出来的DLL的DLLMain的退出地方用到了halt0
DelphiXE2内存加模块升级版.支持32位和64位模块. 已转至新的博客 http://www.raysoftware.cn/?p=51 很多年以前写过内存加载DLL的一片技术. http://b ...
- 一个酷炫的,基于HTML5,Jquery和Css的全屏焦点图特效,兼容各种浏览器
基于HTML5和CSS的焦点图特效,梅花图案的背景很有中国特色,而且还会动哦,效果超炫,推荐下载! 演示图 html代码 <!DOCTYPE html PUBLIC "-//W3C// ...
- 关于Linux的时间与时区
转:http://linux.chinaunix.net/techdoc/beginner/2007/06/22/960790.shtml 首先要说明的是我的系统是fedora,其他系统可能不完全相同 ...
- Android Service实时向Activity传递数据
演示一个案例,需求如下:在Service组件中创建一个线程,该线程用来生产数值,每隔1秒数值自动加1,然后把更新后的数值在界面上实时显示. 步骤如下:1.新建一个android项目工程,取名为demo ...
- asp.net开源CMS推荐
随着网络技术的发展,目前国内CMS的开发商越来越多,各自都有其独特的优势,大家在选择的时候觉得眼花缭乱,不知道选择哪个比较好,我个人认为开源的CMS还是适合我们学习及研究使用,下边就几个国内的asp. ...
- 9本java程序员必读的书
来源:http://mp.weixin.qq.com/s?__biz=MjM5NzA1MTcyMA==&mid=202904638&idx=2&sn=21dd20438e32a ...
- MongoDB安装及简单实验
1.Windows下安装MongoDB http://www.mongodb.org/downloads 下载msi,下一步下一步… 安装完毕后,到安装目录的bin目录下执行mongod启动数据库服务 ...