饿了吗笔试20250314算法题第三题,简单梳理一下自己的解法

思路:首先最外层是动态规划,cnt[k]=cnt[k-1]+m;

这里cnt[k]是k计算result,tmp是(i+k)/gcd(i,k)累加,其中i属于[1,k-1];

然后说一下怎么求tmp,tmp对于k为质数和合数有不同的求法。

如果k是质数,m的结果是(k)*(k-1)*3/2;

而如果k不是质数,先假设它是质数,然后减去一个数dif。

说一下怎么求dif,对于所有比根号k小且被k整除的质数j,有k/j=c;则合数是由质数的j*(1+2+...c-1)*(c*j)/1变成了j(1+2+...c-1)*(c*j)/j,也就是(1+2+...c-1)*(c*j),相比质数少了(j-1)(1+2+...c-1)*(c*j);所以dif就是所有比根号k小且被k整除的质数j,k/j=c,对(j-1)(1+2+...c-1)*(c*j)的累加;然后对于任意正整数n,输出cnt[n]即可;时间复杂度是nlog(n);#笔试#

c++代码如下

#include <bits/stdc++.h>


using namespace std;
const int M = 1000000007;
const int N = 1000000;
bool ip[N+10];//判断是否是质数,true表示为合数
int cnt[N+10];//动态规划的dp数组



vector<int> edge[N+10];
void before(){
	//先把N以内的合数找到
	for(int i=2;i<N;i++){
		for(int j=i+i;j<N;j+=i){
			ip[j]=true;
		}
	}
	//p中存储N中所有素数
	vector<int> p;
	for(int i=2;i<N;i++){
		if(!ip[i]) p.push_back(i);
	}
	//初始化dp
	cnt[2]=3;
	
	for(int i=3;i<N;i++){
		long long tmp=0;
		long long dif=0;
		//如果是合数,求它相比于质数需要减的数dif
		if(ip[i]){
			for(int j=0;p[j]*p[j]<=i;j++){
				//找所有比根号i小的质数,可以推导以下的公式
				if(i%p[j]==0){
					dif+=((p[j]-1)*3/2*(i/p[j])*(i/p[j]-1))%M;
				}
			}
		}	
		tmp=(3*(i)*(i-1)/2)%M;
		
		tmp=(tmp-dif+cnt[i-1])%M;
		cnt[i]=tmp;
		
	}
	
}
void solve(){
	for(int i=2;i<100;i++){
		cout<<cnt[i]<<endl;
	}
}
int main() {
    int t=1;
//    cin>>t;
    before();
    //这里我是自己测试的代码,就没有cin输入了,如果有测试样例,可以改一下。
    while(t--){
		solve();
	}
    return 0;
}

全部评论

相关推荐

03-07 12:00
已编辑
山东大学 Java
野猪不是猪🐗:看得出来人很好,什么都没问面试就结束了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务