欧拉之路
Multiples of 3 and 5
求1000以内3的倍数或者5的倍数的和
考虑容斥,分别加上$3$和$5$的倍数,然后减去$lcm(3,5)$也就是$15$的倍数
1 #include<bits/stdc++.h> 2 using namespace std; 3 int gcd(int a,int b){ 4 if(!b)return a; 5 return gcd(b,a%b); 6 } 7 int s(int x){ 8 return x*(x+1)/2; 9 } 10 int main(){ 11 int a=3,b=5,n=999; 12 int g=a*b/gcd(a,b); 13 printf("%d\n",a*s(n/a)+b*s(n/b)-g*s(n/g)); 14 }
Even Fibonacci numbers
求斐波拉契每一项是偶数值的和
$O(N)$直接DP即可用递推公式$f[n]=f[n-1]+f[n-2]$
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1000010; 4 int dp[N]; 5 long long ans=2; 6 int main(){ 7 int n=4000000; 8 dp[1]=1,dp[2]=2; 9 for(int i=3;;i++){ 10 dp[i]=dp[i-1]+dp[i-2]; 11 if(dp[i]>n)break; 12 if(dp[i]%2)ans+=dp[i]; 13 } 14 cout<<ans; 15 return 0; 16 }
Largest prime factor
找一个数最大的质因子
$O(\sqrt n)$暴力找素数即可
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 int get_max_prime(int x){ 5 int ans=-1; 6 for(int i=2;i<=x&&x!=1;i++) 7 while(x%i==0)x/=i,ans=max(ans,i); 8 if(x!=1)ans=max(ans,x); 9 return ans; 10 } 11 signed main(){ 12 int n=600851475143; 13 printf("%lld\n",get_max_prime(n)); 14 }
Largest palindrome product
查找两个数相乘是回文数的最大的回文数
暴力$O(n^2)$比较,判断是否回文,稍微剪剪枝,T到飞起
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1000010; 4 long long ans=0; 5 int check(int x){ 6 stringstream ss; 7 string s; 8 ss<<x; 9 ss>>s; 10 int len=s.size()-1; 11 for(int i=0;i<=len-i;i++) 12 if(s[i]!=s[len-i])return false; 13 return true; 14 } 15 int main(){ 16 for(int i=999;i>=100;i--){ 17 for(int j=999;j>=100;j--){ 18 if(i*j<=ans)break; 19 ans=max(ans,1ll*check(i*j)*i*j); 20 } 21 } 22 cout<<ans; 23 return 0; 24 }
Smallest multiple
查找能被1-n整除的最小的数
找$lcm(a_1,a_2...a_n)$然后输出即可考虑$O(n)$处理
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int n=20; 6 long long ans=1; 7 for(int i=1;i<=n;i++) 8 { 9 ans/=__gcd(ans,1ll*i); 10 ans*=i; 11 } 12 cout<<ans<<endl; 13 return 0; 14 }
Sum square difference
找平方和 和 和平方的差
$O(n)$依照题意模拟暴力即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long ans; 4 int main(){ 5 for(int i=1;i<=100;i++){ 6 ans+=i*i; 7 } 8 cout<<5050*5050-ans; 9 return 0; 10 }
10001st prime
找第10001个质数
考虑欧拉线性筛,当质数个数等于10001的时候输出即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 int pr[1000010],st[1000010],cnt; 4 int get(int n,int k) 5 { 6 for(int i=2;i<=n;i++) 7 { 8 if(!st[i])st[i]=1,pr[++cnt]=i; 9 if(cnt==k)return pr[k]; 10 for(int j=1;j<=cnt&&pr[j]*i<=n;j++) 11 { 12 st[pr[j]*i]=1; 13 if(i%pr[j]==0)break; 14 } 15 } 16 } 17 int main() 18 { 19 printf("%d\n",get(1000000,10001)); 20 return 0; 21 }
Largest product in a series
给你许多数,找出连续13个乘积最大
考虑暴力模拟取最大值即可,也可以使用队列,并记录其中为0的个数(因为直接除以0会RE)$O(n)$模拟
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long answer; 4 string s="07316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"; 5 int main(){ 6 for(int i=1;i+12<=1000;i++){ 7 long long ans=1; 8 for(int j=0;j<13;j++) 9 ans*=(s[i+j]-'0'); 10 answer=max(answer,ans); 11 } 12 cout<<answer; 13 return 0; 14 }
Special Pythagorean triplet
求\begin{cases} a^2+b^2=c^2 \\ a+b+c=1000 \end{cases} 的唯一解
考虑枚举a,b并通过第二个求出c,再判断是否合法
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int n=1000,ans=-1; 6 for(int i=1;i<=n;i++) 7 for(int j=i+1;j<=n&&i+j<1000;j++) 8 { 9 int k=1000-i-j; 10 if(i*i+j*j==k*k)ans=max(ans,i*j*k); 11 } 12 printf("%d\n",ans); 13 return 0; 14 }
Summation of primes
求2000000以下的素数和
考虑$O(n)$欧拉筛出2000000以下的素数然后相加
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2000010; 4 long long ans,len; 5 int v[N],p[N]; 6 void prime(int n){ 7 for(int i=2;i<=n;i++){ 8 if(!v[i]){ 9 v[i]=1; 10 p[++len]=i; 11 ans+=i; 12 } 13 for(int j=1;j<=len&&i*p[j]<=n;j++){ 14 v[i*p[j]]=1; 15 if(i%p[j]==0)break; 16 } 17 } 18 cout<<ans; 19 } 20 int main(){ 21 prime(2000000); 22 return 0; 23 }
Largest product in a grid
给你一个矩阵,求出连续四个数(可以横竖对角线)使得乘积最大
$O(nm)$,每个点只需要向下,右下,右,右上扩展即可
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 int a[110][110]; 5 signed main() 6 { 7 int n=20,ans=-1; 8 for(int i=1;i<=n;i++) 9 for(int j=1;j<=n;j++) 10 scanf("%lld",&a[i][j]); 11 for(int i=1;i<=n;i++) 12 for(int j=1;j<=n;j++) 13 { 14 int a1=a[i][j]*a[i+1][j]*a[i+2][j]*a[i+3][j]; 15 int a2=a[i][j]*a[i][j+1]*a[i][j+2]*a[i][j+3]; 16 int a3=a[i][j]*a[i+1][j+1]*a[i+2][j+2]*a[i+3][j+3]; 17 int a4=a[i][j]*a[i-1][j+1]*a[i-2][j+2]*a[i-3][j+3]; 18 ans=max(ans,max(a1,max(a2,max(a3,a4)))); 19 } 20 printf("%lld\n",ans); 21 return 0; 22 }
Highly divisible triangular number
求从小到大第一个i使得$d({\sum_{j=1}^i j})>500$
考虑暴力枚举然后$\sqrt n$查找即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=70100000; 4 int check(int n){ 5 int ans=0; 6 for(int i=1;i*i<n;i++){ 7 if(n%i==0)ans+=2; 8 } 9 if((int)sqrt(n)*(int)sqrt(n)==n)ans++; 10 return ans; 11 } 12 int main(){ 13 long long sum=0; 14 for(int i=1;;i++){ 15 sum+=i; 16 if(check(sum)>500){ 17 cout<<sum<<endl; 18 return 0; 19 } 20 } 21 return 0; 22 }
Large sum
高精度加法,然后求前十位
高精度搞一搞
1 #include<bits/stdc++.h> 2 using namespace std; 3 string a[110]; 4 int d[510]; 5 int main(){ 6 int n=100,m=50,k=10; 7 for(int i=1;i<=n;i++){ 8 cin>>a[i]; 9 reverse(a[i].begin(),a[i].end()); 10 } 11 for(int j=0;j<m;j++) 12 for(int i=1;i<=n;i++) 13 d[j]+=(a[i][j]-'0'); 14 for(int j=0;j<m*2;j++) 15 d[j+1]+=d[j]/10,d[j]%=10; 16 int st; 17 for(st=m*2;st&&!d[st];st--); 18 for(int j=st;j>st-k;j--) 19 printf("%d",d[j]); 20 return 0; 21 }
Longest Collatz sequence
给你一个$f(n)=$ \begin{cases} n/2, & \mbox{if }n\mbox{ is even} \\ 3n+1, & \mbox{if }n\mbox{ is odd} \end{cases}
然后求最长能操作的次数
考虑记忆化,但是空间可能开不下,所以指定一个小范围,范围内记忆化即可
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 const int N=10000010; 5 int dp[N]; 6 int ans,answer; 7 int check(int n){ 8 if(n==1)return 1; 9 if(n%2==0) 10 return check(n/2)+1; 11 return check(3*n+1)+1; 12 } 13 signed main(){ 14 for(int i=1;i<=1000000;i++){ 15 int PPP=check(i); 16 if(PPP>ans){ 17 ans=PPP; 18 answer=i; 19 } 20 } 21 cout<<answer; 22 return 0; 23 }
Lattice paths
给你一个n*n方格求出从左上角到右下角的方案数
方案一:可以考虑$dp[i][j]=max(dp[i-1][j],dp[i][j-1])$
方案二:总共可以向下走$n$次,向右走$n$次,所以可以转换成一个组合数问题,也就是从$2n$里面选择$n$个,$C_{2n}^n$
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 int C(int n){ 5 int fac=1; 6 for(int i=n+1;i<=2*n;i++) 7 (fac*=i)/=(i-n); 8 return fac; 9 } 10 signed main(){ 11 int n=20; 12 printf("%lld\n",C(20)); 13 return 0; 14 }
Power digit sum
高精度乘法
暴力模拟搞一搞
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100010; 4 int a[N]; 5 long long ans; 6 int main(){ 7 a[1]=1; 8 int n=1000; 9 for(int i=1;i<=1000;i++){ 10 for(int j=1;j<=20000;j++){ 11 a[j]*=2; 12 } 13 for(int j=1;j<=20000;j++){ 14 a[j+1]+=a[j]/10; 15 a[j]%=10; 16 } 17 } 18 for(int i=1;i<=20000;i++) 19 ans+=a[i]; 20 cout<<ans; 21 return 0; 22 }
Number letter counts
求出1-1000用英文表示需要多少个字符
怪恶心的
模拟每一个数转换成英文要多少个字符即可
1 #include<bits/stdc++.h> 2 int ud100[20]={0,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8}; 3 int ov100[10]={0,0,6,6,5,5,5,7,6,6}; 4 int len(int x){ 5 if(x<20)return ud100[x]; 6 else if(x<100)return ud100[x%10]+ov100[x/10]; 7 else if(x<1000){ 8 if(x%100==0)return ud100[x/100]+7; 9 else return ud100[x/100]+len(x%100)+10; 10 11 } 12 else return 11; 13 } 14 15 int main(){ 16 int sum=0; 17 for(int i=1;i<=1000;i++) 18 sum+=len(i); 19 printf("%d\n",sum); 20 return 0; 21 }
Maximum path sum I
数字三角形
$dp[i][j]$表示第i行第j列能得到的最大价值
考虑$dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+a[i][j]$即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 int ans; 4 int a[110][110]; 5 int main(){ 6 int n=15; 7 for(int i=1;i<=n;i++){ 8 for(int j=1;j<=i;j++){ 9 scanf("%d",&a[i][j]); 10 a[i][j]+=max(a[i-1][j],a[i-1][j-1]); 11 ans=max(ans,a[i][j]); 12 } 13 } 14 cout<<ans; 15 return 0; 16 }
Counting Sundays
数星期日在一个月的第一天有多少个
首先题目给的是1900年1月1日的,我们先算出1901年1月1日是星期二,然后判断每一个月多少天模拟即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 4 int main() 5 { 6 int sum=0,now=1,y,m,d; 7 int Y=2000; 8 for(y=1901;y<=2000;y++) 9 for(m=1;m<=12;m++) 10 for(d=1;d<=day[m]+(m==2)*((y%4==0)-(y%100==0)+(y%400==0));d++) 11 { 12 now++; 13 if(now==7) 14 { 15 now=0; 16 if(d==1)sum++; 17 } 18 } 19 printf("%d\n",sum); 20 return 0; 21 }
Factorial digit sum
阶乘求各位之和
高精度搞一搞
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100010; 4 int a[N]; 5 long long ans; 6 int main(){ 7 1[a]=1; 8 for(int i=1;i<=100;i++){ 9 for(int j=1;j<=20000;j++){ 10 j[a]*=i; 11 } 12 for(int j=1;j<=20000;j++){ 13 (j+1)[a]+=j[a]/10; 14 j[a]%=10; 15 } 16 } 17 for(int i=1;i<=20000;i++) 18 ans+=i[a]; 19 cout<<ans; 20 return 0; 21 }
Amicable numbers
记d(i)为i的真因数和
定义两个数a,b
$if(d(a)=b \&\& d(b)=a)$
那么这两个数都是亲和数,这一对数称为亲和数对
求出10000以内的亲和数之和
考虑欧拉筛出$d(i)$然后减去自己得到每个输得真因数和,然后$O(n)$找出亲和数相加即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=10100; 4 int f[N],g[N],p[N],used[N]; 5 int len; 6 long long ans; 7 inline void get_f(int n){ 8 f[1]=g[1]=1; 9 for(int i=2;i<=n;i++){ 10 if(!used[i]){ 11 used[i]=1; 12 p[++len]=i; 13 g[i]=f[i]=i+1; 14 } 15 for(int j=1;j<=len&&i*p[j]<=n;j++){ 16 used[p[j]*i]=1; 17 if(i%p[j]==0){ 18 g[i*p[j]]=g[i]*p[j]+1; 19 f[i*p[j]]=f[i]/g[i]*g[i*p[j]]; 20 break; 21 } 22 else{ 23 f[i*p[j]]=f[i]*f[p[j]]; 24 g[i*p[j]]=1+p[j]; 25 } 26 } 27 } 28 for(int i=1;i<=n;i++) 29 f[i]-=i; 30 } 31 int main(){ 32 get_f(10000); 33 for(int i=1;i<10000;i++){ 34 if(f[f[i]]==i&&i!=f[i])ans+=i; 35 } 36 cout<<ans; 37 return 0; 38 }
Names scores
给你许多名字,求出名字序号*每个字母的排名,累加
先处理恶心的格式,然后排序,然后计算每个数的分值,相加即可
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 string a[100010]; 5 inline ll idx(string x){ 6 ll fac=0; 7 for(int i=0;i<x.size();i++) 8 fac+=(x[i]-'A'+1); 9 return fac; 10 } 11 int main(){ 12 int n=0; 13 ll ans=0; 14 while(cin>>a[++n]); 15 sort(a+1,a+1+n); 16 for(int i=1;i<=n;i++){ 17 // if(a[i]=="COLIN")printf("%lld\n",1ll*(i-1)*idx(a[i])); 18 ans+=1ll*(i-1)*idx(a[i]); 19 } 20 printf("%lld\n",ans); 21 return 0; 22 }
Non-abundant sums
定义一个数$n$,$d(n)$为$n$的真因数之和
$if(d(n)=n)$称为完全数
$if(d(n)>n)$称为盈数
$if(d(n)<n)$称为亏数
已知大于28123都能表示为两个盈数相加
求出不能表示为两个盈数相加的数的总和
考虑$O(n)$筛出$d(i)$然后再计算出盈数push进一个vector,再双重for循环打标机,最后累计一遍没有打上标记的即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=30000; 4 int len,ans; 5 int g[N],f[N],v[N],p[N]; 6 vector<int>res; 7 void get_f(int n){ 8 g[1]=f[1]=1; 9 for(int i=2;i<=n;i++){ 10 if(!v[i]){ 11 v[i]=1, 12 p[++len]=i; 13 g[i]=f[i]=i+1; 14 } 15 for(int j=1;j<=len&&p[j]*i<=n;j++){ 16 v[p[j]*i]=1; 17 if(i%p[j]==0){ 18 g[i*p[j]]=g[i]*p[j]+1; 19 f[i*p[j]]=f[i]/g[i]*g[i*p[j]]; 20 } 21 else{ 22 g[i*p[j]]=p[j]+1; 23 f[i*p[j]]=f[i]*f[p[j]]; 24 } 25 } 26 } 27 for(int i=1;i<=n;i++) 28 f[i]-=i; 29 } 30 int main() 31 { 32 get_f(28123); 33 34 for(int i=1;i<=28123;i++){ 35 if(f[i]>i)res.push_back(i); 36 } 37 memset(v,0,sizeof v); 38 for(int i=0;i<res.size();i++){ 39 for(int j=i;j<res.size();j++){ 40 v[res[i]+res[j]]=1; 41 } 42 } 43 for(int i=1;i<=28123;i++){ 44 if(!v[i])ans+=i; 45 } 46 cout<<ans; 47 return 0; 48 }
Lexicographic permutations
给你一个n=10的(0到9)序列,求出排名第1000000的序列是多少
考虑搜索或者next_permutation()O(k)求出排列
但还有一种更高级的方法——逆康托展开
具体原理链接已挂,不做解释
能$O(n \log n)$算出排列,但是一般由于阶乘问题,n不会很大
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 int k=1000000,n=10; 5 ll fac[11]; 6 vector<int>s; 7 int main(){ 8 fac[0]=1; 9 for(int i=1;i<=n;i++) 10 fac[i]=fac[i-1]*i,s.push_back(i); 11 k--; 12 for(int i=9;i>=0;i--){ 13 int p=k/fac[i]; 14 printf("%d ",s[p]-1); 15 s.erase(lower_bound(s.begin(),s.end(),s[p])); 16 k%=fac[i]; 17 } 18 19 }
1000-digit Fibonacci number
求出第几项斐波拉契位数大于等于1000
高精度模拟
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct node{ 4 int a[110010]; 5 int len; 6 node(){ 7 memset(a,0,sizeof a); 8 len=0; 9 } 10 node operator+(const node &x)const{ 11 node c; 12 for(register int i=1;i<=1000;i++) 13 c.a[i]=a[i]+x.a[i]; 14 for(register int i=1;i<=1000;i++){ 15 c.a[i+1]+=c.a[i]/10; 16 c.a[i]%=10; 17 if(c.a[i])c.len=max(c.len,i); 18 } 19 return c; 20 } 21 }f[4]; 22 int main(){ 23 24 f[1].a[1]=1; 25 f[2].a[1]=1; 26 for(int i=3;;i++){ 27 f[(i+1)%3]=f[i%3]+f[(i+2)%3]; 28 if(f[(i+1)%3].len>=1000){ 29 cout<<i; 30 return 0; 31 } 32 } 33 34 }
Reciprocal cycles
求出1000以内对于每一个$i$,$\frac{1}{i}$循环节位数最大的一个i并输出
循环节可能很大,所以我们模拟人工运算,去拿余数*10继续试除,考虑拿余数记录这一位是否重复(如果余数相同,那么后面的肯定也还是相同的),所以只需要打标记,如果访问到了就拿这一次的减去上次访问的就是循环节的长度了
1 #include<bits/stdc++.h> 2 using namespace std; 3 int f[100001]; 4 int first[100001]; 5 int pre[1001]; 6 bool flag; 7 int ans,answer; 8 void work(int k,int x,int i){ 9 if(flag)return; 10 k*=10; 11 k%=x; 12 if(pre[k]){ 13 f[x]=i-pre[k]; 14 flag=1; 15 return; 16 } 17 pre[k]=i; 18 work(k,x,i+1); 19 } 20 int main(){ 21 for(int i=1;i<=1000;i++){ 22 flag=0; 23 memset(pre,0,sizeof pre); 24 work(1,i,1); 25 if(f[i]>ans){ 26 ans=f[i]; 27 answer=i; 28 } 29 } 30 cout<<ans<<" "<<answer<<endl; 31 return 0; 32 }
Quadratic primes
给你$n^2+an+b$其中$(|a|<1000,|b|\leq 1000)$
求出一对$a,b$使得$n$从0开始,连续答案的都是素数的最长连续个数
考虑先晒出素数打标记然后暴力模拟
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=10000000; 4 int len,ans,answer; 5 int p[1000010]; 6 int v[N+1]; 7 void get(){ 8 for(int i=2;i<=N;i++){ 9 if(!v[i]){ 10 v[i]=2; 11 p[++len]=i; 12 } 13 for(int j=1;j<=len&&i*p[j]<=N;j++){ 14 v[i*p[j]]=1; 15 if(i%p[j]==0)break; 16 } 17 } 18 } 19 int main(){ 20 get(); 21 for(int a=-1000;a<=1000;a++){ 22 for(int b=-1000;b<=1000;b++){ 23 for(int l=0;;l++){ 24 if(l*l+a*l+b<0||v[l*l+a*l+b]!=2)break; 25 if(l+1>ans)ans=l+1,answer=a*b; 26 ans=max(ans,l+1); 27 // printf("%d ",ans); 28 } 29 } 30 } 31 cout<<answer; 32 33 return 0; 34 }
Number spiral diagonals
类似于螺旋矩阵那种,给你边长求对角线之和
这种是奇偶分开考虑,这里只有奇数的,找个规律发现下一个增加的是2,2,2,2,4,4,4,4,6,6,6,6...然后循环即可
1 #include<bits/stdc++.h> 2 using namespace std;给你 3 long long ans,pre=1; 4 int main(){ 5 int n=1001; 6 for(int i=2;i<=n;i+=2){ 7 for(int j=1;j<=4;j++){ 8 pre=pre+i; 9 ans+=pre; 10 } 11 } 12 cout<<ans+1; 13 return 0; 14 }
Distinct powers
给你一个$a*b$的方阵,其中$v[i][j]=i^j$问你去重后总共有多少个元素
首先你可以考虑高精度这精度要上天了但是我很懒
我们想,对于一个数$k$,他可能会和$k^2,k^3,k^4...k^x$重合,所以我们只需要考虑枚举最简的k即可
然后记录他能到达多少次幂,ans加一加,时间复杂度是$O(nm)$
然后思考n,m更大时候的做法
对于$2,2^2,2^3,2^4$他能取得种类一定和$3,3^2,3^3,3^4$是一样的
所以我们考虑先$O(nlogm)$求出所有的种类数(因为最多要考虑的只有$\log m$个也就是2次幂),然后$O(n)$走一遍,打个标记就行了
整体时间复杂度$O(nlogm)$
$O(n^2)$
1 #include<bits/stdc++.h> 2 #define n 101 3 #define m 6001 4 using namespace std; 5 bool used[n]; 6 bool flag[m]; 7 int ans=0,t; 8 int main(void) 9 { 10 for(int i=2,j;i<n;i++){ 11 if(!used[i]){ 12 t=i; 13 memset(flag,0,sizeof flag); 14 for(j=2;j<n;j++){ 15 t=t*i; 16 if(t>=n)break; 17 used[t]=true; 18 } 19 for(int k=1;k<j;k++) 20 for(int l=2;l<n;l++) 21 flag[k*l]=true; 22 for(int k=2;k<m;k++){ 23 if(flag[k]){ 24 ans++; 25 } 26 } 27 } 28 29 } 30 printf("%d\n",ans); 31 return 0; 32 }
$O(n \log m)$
1 #include<bits/stdc++.h> 2 #define n 1001 3 #define m 600001 4 using namespace std; 5 bool used[n]; 6 bool flag[m]; 7 int check[m]; 8 int ans=0,t,res; 9 int main(void) 10 { 11 // ans=(n-2)*(n-2); 12 for(int k=1;k<log2(n);k++){//提前预处理 13 for(int l=2;l<n;l++){ 14 if(!flag[k*l]) 15 flag[k*l]=true,res++; 16 } 17 check[k]=res; 18 } 19 for(int i=2,j;i<n;i++){//因为有标记,所以是O(n)的复杂度 20 if(!used[i]){ 21 t=i; 22 memset(flag,0,sizeof flag); 23 for(j=2;j<n;j++){ 24 t=t*i; 25 if(t>=n)break; 26 used[t]=true; 27 } 28 ans+=check[j-1]; 29 } 30 31 } 32 printf("%d\n",ans); 33 return 0; 34 }
Digit fifth powers
让你找出所有的各位数字5次幂之和加起来等于本身的数,并输出他们的和
考虑暴力计算每一位的和,但是这里的上限是未知的,所以需要有一个判断
如果i位数,每一位都是9加起来还没这个数大,那后面的基本都不可能了,返回就可以了
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n=5; 4 string s; 5 long long ans,res; 6 long long fac[10]; 7 int main(){ 8 for(int i=1;i<=9;i++) 9 fac[i]=pow(i,n); 10 for(int i=2;i;i++){ 11 res=0; 12 stringstream ss; 13 ss<<i; 14 ss>>s; 15 for(int j=0;j<s.size();j++) 16 { 17 res+=fac[s[j]-'0']; 18 if(res>i)break; 19 } 20 if(res==i)ans+=i; 21 if(fac[9]*s.size()<i)break; 22 } 23 cout<<ans; 24 return 0; 25 }