题目是求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 推公式,筛素数的更多相关文章

  1. 【板子】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 ...

  2. ACM-ICPC 2018 南京赛区网络预赛 J题Sum(线性筛素数)

    题目链接:https://nanti.jisuanke.com/t/30999 参考自博客:https://kuangbin.github.io/2018/09/01/2018-ACM-ICPC-Na ...

  3. codeforces 185A Plant(推公式)

    Plant [题目链接]Plant [题目类型]推公式 &题解: 这个是可以推公式的: 每年的总个数是4^n个,设n年时向上的个数是x个,向下的个数是y个,那么n+1年时,向上的个数是3* x ...

  4. 欧拉函数O(sqrt(n))与欧拉线性筛素数O(n)总结

    欧拉函数: 对正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目. POJ 2407.Relatives-欧拉函数 代码O(sqrt(n)): ll euler(ll n){ ll ans=n; ...

  5. 全网一定不是最好懂的C++线性筛素数

    Part 0:概念 先给几个概念(很重要): 合数:如果\(xy=z\text{且}x,y\text{为正整数}\),我们就说\(x,y\text{是}z\text{的合数}\) 素数:如果数\(a\ ...

  6. CF449C Jzzhu and Apples (筛素数 数论?

    Codeforces Round #257 (Div. 1) C Codeforces Round #257 (Div. 1) E CF450E C. Jzzhu and Apples time li ...

  7. HDU 4873 ZCC Loves Intersection(JAVA、大数、推公式)

    在一个D维空间,只有整点,点的每个维度的值是0~n-1 .现每秒生成D条线段,第i条线段与第i维度的轴平行.问D条线段的相交期望. 生成线段[a1,a2]的方法(假设该线段为第i条,即与第i维度的轴平 ...

  8. HDU 4870 Rating(概率、期望、推公式) && ZOJ 3415 Zhou Yu

    其实zoj 3415不是应该叫Yu Zhou吗...碰到ZOJ 3415之后用了第二个参考网址的方法去求通项,然后这次碰到4870不会搞.参考了chanme的,然后重新把周瑜跟排名都反复推导(不是推倒 ...

  9. 洛谷P3383 【模板】线性筛素数

    P3383 [模板]线性筛素数 256通过 579提交 题目提供者HansBug 标签 难度普及- 提交  讨论  题解 最新讨论 Too many or Too few lines 样例解释有问题 ...

随机推荐

  1. zoj 3599 Game 博弈论

    K倍动态减法游戏!!! 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4683 代码如下: #include<ios ...

  2. 取消 EditText 自动聚焦弹出输入法界面

    方法一(实测可行): 参考http://www.cnblogs.com/dream-cichan/p/aaaa.html 当我点击跳转至一个带有EditText的界面后,模拟器中的软键盘会自动弹出,严 ...

  3. NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.

    解决办法: http://stackoverflow.com/questions/4037125/namespace-err-an-attempt-is-made-to-create-or-chang ...

  4. 随机森林分类(Random Forest Classification)

    其实,之前就接触过随机森林,但仅仅是用来做分类和回归.最近,因为要实现一个idea,想到用随机森林做ensemble learning才具体的来看其理论知识.随机森林主要是用到决策树的理论,也就是用决 ...

  5. .net与linux

    Mono是什么? http://blog.sina.com.cn/s/blog_693ffe760100k5uh.html Mono是一个开放源代码,Linux版的Microsfot.NET开发平台 ...

  6. Nim语言:Pascal的语法,Python的缩进

    http://nim-lang.org/ 德国人Andreas Rumpf的作品,原因是他对过去使用的每种语言都不满意(Pascal也不满意?).以前叫Nimrod语言,从0.96版本开始改名为Nim ...

  7. C++:析构函数

    析构函数的特点: 1.析构函数与类名相同,但它前面必须加上波浪号~ 2.析构函数不返回任何值,在定义析构函数时,是不能说明它的类型的,甚至说明void类型也不能 3.析构函数没有参数,因此不能被重载. ...

  8. ubuntu set host name

    http://wiki.joyent.com/wiki/display/jpc2/Setting+the+Host+Name+on+a+Linux+VM Set the host name in th ...

  9. RecyclerView(5)官方教程带简单示例

    Create Lists The RecyclerView widget is a more advanced and flexible version of ListView. This widge ...

  10. bzoj2482

    还是像以前那样维护下次出现位置,计算影响 其实不难,思维盲点,受到做最大子段和的影响 其实这里可以直接维护当前每个位置的子段和,再记录一个历史最大和 当然tag也需要记录当前tag和历史(距离上次pu ...