zoukankan      html  css  js  c++  java
  • 欧拉之路

    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 } 
  • 相关阅读:
    工作交接
    .NET 利用反射将对象数据添加到数据库
    【C#】IPAddress.Any 解决本地ip和服务器ip切换问题
    【C#】警告System.Configuration.ConfigurationSettings.AppSettings" 已过时
    【C#】TcpListener的对象“已过时”的编译警告
    大城小胖这几年积累的动画库、手势库、物理引擎库
    select option项选择后跳转页面
    360引起的Soap的java.io.EOFException错误
    linux安装mysql-5.7.22与数据自动备份
    性能测试流程
  • 原文地址:https://www.cnblogs.com/hualian/p/13824401.html
Copyright © 2011-2022 走看看