很巧,这次周赛又放了一个数学问题进去,纯数学。
但是很不巧的是没做出来,自己手动模了半天,没有找到规律,后面结束的时候发现打这个题目最好要用到质因数的思想。
题目大致意思:
求1~n整数中(假设取k),因数为9的个数。
1.k只有一个因数,且n=a的8次方
2.k有两个因数a,b 且k=a的平方乘上b的平方
小tip:做好先筛出所有质数先,通过单调性质,利用双指针求,也可以同步暴力8次方。
这个题目涉及的思想还是挺多的,好久没有打一遍筛素数了.....
#include<bits/stdc++.h>
using namespace std;
#define int long long
int ai(int x){
return x&(-x);
}
//
int ok=1;
const int op=1e7+2;
vector<bool>prime(op);
//bool的形式可以少占用点内存
vector<bool>is_prime(op,1);
void shai(int m){
//一开始就直接给0 1赋值为false,因为不是质数,是质数的就打上1的标签
//现在prime这个数组里面所有的数就全部都是质数了
for(int i=2;i<=m;i++){
if(is_prime[i]){
for(int j=i*i;j<=m;j+=i){
is_prime[j]=0;
}
}
}
for(int i=2;i<=m;i++){
if(is_prime[i]){
prime[++ok]=i;
}
}
}
int powll(int a){
//8次方
int sum=1;
for(int i=1;i<=8;i++){
sum*=a;
}
return sum;
}
signed main(){
int n;cin>>n;
int m=sqrt(1.0*n+0.5);
//平方后取整
//线性筛
is_prime[0]=is_prime[1]=false;
int ans=0;
int j=ok;
//从后往前不断的去找i的平方数和j的平方数之积,i是左端点,j是右端点
for(int i=1;i<=ok;i++){
//质数的个数和数量,prime里面存储的是所有1到m的质数
while(prime[i]*prime[i]*prime[j]*prime[j]>n&&j>i)j--;
ans+=max(0ll,j-i);
//j-i就是这一轮的总个数
}
//我真的是很想知道,这个双指针的思想到底要多少次打了以后才能在比赛的时候写出来
/*for(int i=1;i<=ok;i++){if(powll(prime[i])<=n)ans++;else break;}*/
//判断八次方是否满足
cout<<ans<<endl;
}
没事就回来看看这个代码,还是很有参考意义的,筛质数,跑暴力,双指针.....