Discription
This time I need you to calculate the f(n) . (3<=n<=1000000)
f(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 some things.
gcd(a,b) means the greatest common divisor of a and b.
Input
There are several test case. For each test case:One integer n(3<=n<=1000000). The end of the in put file is EOF.
Output
For each test case:
The output consists of one line with one integer f(n).
Sample Input
3
26983
Sample Output
3
37556486
题意
f(n)= Gcd(3)+Gcd(4)+…+Gcd(i)+…+Gcd(n).
Gcd(n)=gcd(C[n][1],C[n][2],……,C[n][n-1])
C[n][i]为组合数,从n个中选i个。
给定n,求解f(n)
思路
找不到规律,打表找规律。
Gcd(n)的规律:
若是n素数,则是gcd(n)为它本身;
若是合数,且只有一个质因子,则是它最大的质因子。
若有两个质因子,则是1。
打表代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL INF=1000000000;
const LL MAX=1e6+50;
LL com[100][100];
void YangHui()
{
memset(com, 0, sizeof(com));
for (int i=1; i<=50; i++)
{
com[i][0]=com[i][i] = 1;
for (int j=1; j<i; j++)
com[i][j]=com[i-1][j-1]+com[i-1][j];
}
}
int main()
{
YangHui();
for(int n=1; n<=50; n++)
{
LL ans=com[n][1];
for(int i=2; i<n; i++)
ans=__gcd(ans, com[n][i]);
printf("%I64d\n",ans);
}
return 0;
}
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAX = 1000010;
bool vis[MAX];
int n;
LL cnt[MAX]; // 记录素因子个数, 为素数时,cnt = 0
LL maxnum[MAX]; // 记录最大素因子
LL ans[MAX];
void Prime()
{
for(int i = 2; i < MAX; i++)
{
if(!vis[i])
{
vis[i]=1;
for(int j=2;j*i<MAX;j++)
{
cnt[j*i]++;//统计某个数被记录的次数
vis[i*j]=1;//标记非素数
maxnum[i*j]=i;//某个数最大的质因子
}
}
}
}
void init()
{
for(int i=3; i<MAX; i++) // 预处理
{
int x;
if(cnt[i]==0)//记录次数为0,表示为素数
x=i;
else if(cnt[i]==1)
x=maxnum[i];
else
x=1;
ans[i]=ans[i-1] + x;
}
}
int main()
{
Prime();
init();
while(scanf("%d", &n)!=EOF)
{
printf("%I64d\n", ans[n]);
}
return 0;
}

本文探讨了如何求解特定GCD序列问题,通过分析GCD(n)的规律,提出了预处理策略,针对每个n计算从3到n的Gcd序列和。利用素数筛法预先计算每个数的素因子个数和最大素因子,以此优化求解过程。
496

被折叠的 条评论
为什么被折叠?



