欧拉之路

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
",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
",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
",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

egin{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
",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
",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)=$ egin{cases} n/2, & mbox{if }nmbox{ is even} \ 3n+1, & mbox{if }nmbox{ 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
",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
",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
",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
",1ll*(i-1)*idx(a[i]));
18         ans+=1ll*(i-1)*idx(a[i]);
19     }
20     printf("%lld
",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
",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
",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 } 
原文地址:https://www.cnblogs.com/hualian/p/13824401.html