饿了吗笔试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;
}

全部评论

相关推荐

10-30 18:32
同济大学 C++
-&nbsp;面试常见题目:1.&nbsp;求最大公约数:gcd(a,b)&nbsp;=&nbsp;gcd(b,r)&nbsp;&nbsp;因为&nbsp;a&nbsp;=&nbsp;b&nbsp;*&nbsp;q&nbsp;+&nbsp;r(余数)=&gt;&nbsp;gcd(a,b)&nbsp;=&nbsp;gcd(b,&nbsp;a&nbsp;%&nbsp;b)&nbsp;=&nbsp;...&nbsp;gcd(x,0)&nbsp;=&nbsp;x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;solution:&nbsp;&nbsp;int&nbsp;gcd(int&nbsp;a,&nbsp;int&nbsp;b){return&nbsp;gcd(a,&nbsp;a%b);2.&nbsp;a找到一个整数中,从右往左第一个1所在的位置:&nbsp;求lsb?方法一:有一个指针0x1&nbsp;每次判断&nbsp;(n&nbsp;&amp;&nbsp;lsb)&nbsp;==0&nbsp;如果是0的话,进入循环然后&nbsp;lsb&nbsp;&lt;&lt;=&nbsp;1;&nbsp;直到(n&nbsp;&amp;&nbsp;lsb)&nbsp;!=0&nbsp;方法二:&nbsp;的&nbsp;return&nbsp;n&nbsp;&amp;&nbsp;(-n);3.&nbsp;不用中间变量把&nbsp;a和b换掉。两种思路:&nbsp;a&nbsp;=&nbsp;a+&nbsp;b;&nbsp;b&nbsp;=&nbsp;a&nbsp;-b;&nbsp;a&nbsp;=&nbsp;a&nbsp;-&nbsp;b;&nbsp;a&nbsp;=&nbsp;a^&nbsp;b;&nbsp;b&nbsp;=&nbsp;a&nbsp;^b;&nbsp;a&nbsp;=a&nbsp;^b;-&nbsp;语句:1.&nbsp;三目运算符号&nbsp;&nbsp;k&nbsp;=&nbsp;i&nbsp;&gt;&nbsp;j&nbsp;?&nbsp;&nbsp;i&nbsp;:&nbsp;j;2.&nbsp;指令语句:if&nbsp;else,&nbsp;switch&nbsp;case&nbsp;break;&nbsp;while&nbsp;true;&nbsp;do&nbsp;while;&nbsp;for;&nbsp;break;&nbsp;continue;-&nbsp;数组:1.&nbsp;一维数组:数组的内存空间:一片连续的内存空间,并提前分配好大小相等的小空间[一维内存空间图片]2.&nbsp;为什么大多数语言都是从零开始?因为这个&nbsp;i代表的是内存空间的偏移量:i_add&nbsp;=&nbsp;base_add&nbsp;+&nbsp;i&nbsp;*&nbsp;sizeof(elen)3.&nbsp;常见:数组的效率&nbsp;&gt;&nbsp;链表的效率内存:链表内存消耗(离散)&nbsp;&gt;&nbsp;数组(连续)cpu:&nbsp;数组可以利用空间局部性4.&nbsp;c语言不检查数组是否越界。无论是否越界他都会执行。-&nbsp;二维数组:1.&nbsp;本质是:一维数组,在每个内存子空间下面再竖向添加一个子空间[二维数组内存图片]2.&nbsp;数组的初始化:推荐&nbsp;int&nbsp;matrix[2][3]&nbsp;=&nbsp;{0};3.&nbsp;常量数组:不能修改数组的元素。-&nbsp;好处:防止篡改,安全性高;有助于编译器优化程序。&nbsp;应用场景:存储不会发生改变的数据(静态数据)-&nbsp;例子:扑克牌发牌
笔试
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务