CF1542C Strange Function

CF1542C Strange Function

原题链接
题意:

这里f[i]表示不是i因子的最小数。比如f[1]=2,f[2]=3,f[3]=2…
题目给一个n,求出 ∑ i = 1 n \sum_{i=1}^n i=1nf[i]。

题解:

可以推出
f(1)=2
f(2)=3
f(3)=2
f(4)=3
f(5)=2
f(6)=4


f(7)=2
f(8)=3
f(9)=2
f(10)=3
f(11)=2
f(12)=5


f(13)=2
f(14)=3
f(15)=2
f(16)=3
f(17)=2
f(18)=4

可以得出以下规律:如果i是奇数,f(i)是2。并且如果六个数分成一块的话,前5个数一定是23232(可以证明),关键在第六个数,当他是1*2*3的整数倍时,那f(i)至少是4。当他是1*2*3*2的整数倍数,f(i)至少是5,当他是1*2*3*2*5的整数倍时,f(i)至少是7…
到此,我们可以一层层加,假设刚开始全部都是1,如果1~i里面有N个数是1*2的倍数,则ans+N,如果1~i里面有N个数是1*2*3的倍数,则ans+N…
根据估算,n不超过1e16,f(n)不超过40,所以打表求出a[i],i ∈ \in (1,40)。答案就是1~40里n/a[i]之和。

打表求出以下数a[i]:
1 2 6 12 60 60 420 840 2520 2520 27720 27720 360360 360360 360360 720720 12252240 12252240 232792560 232792560 232792560 232792560 5354228880 5354228880 26771144400 26771144400 80313433200 80313433200 2329089562800 2329089562800 72201776446800 144403552893600 144403552893600 144403552893600 144403552893600 144403552893600 5342931457063200 5342931457063200 5342931457063200 5342931457063200
第i个数表示他能整除1~i里所有数,同时该数又是最小的。比如a[3]=6,6可以整除1,2,3,是满足条件的最小数。a[5]=60,60可以整除1,2,3,4,5。

代码:

#include
using namespace std;
typedef long long ll;
const int M=1e9+7;
ll gcd(ll a,ll b)
{
	return b==0?a:gcd(b,a%b);
}
int main()
{
	ll a[100];
	a[0]=1;
	a[1]=1;
	for(ll i=2;i<=40;i++)
	{
		ll d=gcd(a[i-1],i);
		a[i]=a[i-1]*i/d;
	}
	int T;
	cin>>T;
	while(T--)
	{
		ll n,ans=0;
		cin>>n;
		for(int i=0;i<=40;i++)//从0开始是假设初始不是都为1,而是为0,这样使代码更统一。
		{
			ans=(ans+n/a[i])%M;
		}
		cout<<ans<<endl;
	}

	
	return 0;
}

你可能感兴趣的:(算法练习,acm竞赛,math.h)