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

    Coin sums

    有面值$1,2,5,10,20,50,100,200$问组成面值200有多少种方法

    直接背包带走

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int a[10]={0,1,2,5,10,20,50,100,200};
     4 int dp[300];
     5 int main(){
     6     dp[0]=1;
     7     for(int i=1;i<=8;i++){
     8         for(int j=a[i];j<=200;j++)
     9             dp[j]+=dp[j-a[i]];
    10     }
    11     cout<<dp[200];
    12     return 0;
    13 } 

    Pandigital products

    问有$x*y=z$其中$x,y,z$总共$9$位,包含了$1~9$所有数字,问这样的合法等式结果加起来是多少(相同的只加一次)

    就一个暴力模拟,注意判断,我的判断用的状压

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 long long check,ans;
     4 int main(){
     5     for(int i=1;i<=10000;i++){
     6 //        printf("%d ",i);
     7         for(int j=1;j<=sqrt(i);j++){
     8             int a=i,len=0;
     9             if(i%j==0){
    10                 check=0;
    11                 while(a){
    12                     if(check&(1<<(a%10)))goto end;
    13                     check|=1<<(a%10);
    14                     a/=10;
    15                     len++; 
    16                 }
    17                 a=j;
    18                 while(a){
    19                     if(check&(1<<(a%10)))goto end;
    20                     check|=1<<(a%10);
    21                     a/=10;
    22                     len++; 
    23                 }
    24                 a=i/j;
    25                 while(a){
    26                     if(check&(1<<(a%10)))goto end;
    27                     check|=1<<(a%10);
    28                     a/=10;
    29                     len++; 
    30                 }
    31                 if(len!=9)goto end;
    32 //                bitset<10> b;
    33 //                b=check;
    34                 check>>=1;
    35                 for(int k=1;k<=9;k++){
    36                     if((check&1)==0)goto end;
    37                     check>>=1;
    38                 }
    39 //                cout<<b<<endl;
    40                 ans+=i;
    41 //                cout<<i<<" "<<j<<" "<<i/j<<" "<<len<<endl;
    42             }
    43             else continue;
    44             break;
    45             end:
    46                 continue;
    47         }
    48     }
    49     cout<<ans;
    50     return 0;
    51 } 

    Digit cancelling fractions

    49/98是一个有趣的分数,因为缺乏经验的数学家可能在约简时错误地认为,等式49/98 = 4/8之所以成立,是因为在分数线上下同时抹除了9的缘故。

    我们也会想到,存在诸如30/50 = 3/5这样的平凡解。

    这类有趣的分数恰好有四个非平凡的例子,它们的分数值小于1,且分子和分母都是两位数。

    将这四个分数的乘积写成最简分数,求此时分母的值。

    直接枚举分子分母是一位数的,然后枚举删去的那个数,化简比较就行了

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 long long check,ans;
     4 int s1=1,s2=1;
     5 int main(){
     6     for(int i=1;i<10;i++){
     7         for(int j=i+1;j<10;j++){
     8             int x=i/__gcd(i,j),
     9                 y=j/__gcd(i,j);
    10             for(int k=1;k<=9;k++){
    11                 int a1=i*10+k,
    12                     a2=k*10+j;
    13                 if(x==a1/__gcd(a1,a2)&&y==a2/__gcd(a1,a2)){
    14                     s1*=a1,s2*=a2;
    15                     cout<<a1<<" "<<a2<<endl;
    16                 }
    17                 a1=k*10+i,
    18                 a2=j*10+k;
    19                 if(x==a1/__gcd(a1,a2)&&y==a2/__gcd(a1,a2)){
    20                     s1*=a1,s2*=a2;
    21                     cout<<a1<<" "<<a2<<endl;
    22                 }
    23             }
    24         }
    25     }
    26     printf("%d %d",s1/__gcd(s1,s2),s2/__gcd(s1,s2));
    27     return 0;
    28 } 

    Digit factorials

    和之前一样,直接暴力搞吧

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 long long fac[11];
     4 long long ans,res;
     5 int main(){
     6     fac[0]=1;
     7     for(int i=1;i<=9;i++)
     8         fac[i]=fac[i-1]*i;
     9     for(int i=3;;i++){
    10         int a=i,len=0;
    11         res=0;
    12         while(a){
    13             res+=fac[a%10];
    14             a/=10;
    15         }
    16         if(res==i)ans+=i;
    17         if(1ll*(len+1)*fac[9]<i)break;
    18 //        printf("%d ",i);
    19     }
    20     cout<<ans;
    21     return 0;
    22     
    23 } 

    Circular primes

    一个数成为圆周素数是当它最后一位移到第一位,组成的数都是素数,求1000000以下的圆周素数

    先欧拉筛注意筛到1e8,然后循环判断即可

    #include<bits/stdc++.h>
    using namespace std;
    int p[10000010];
    int v[10000010];
    int ans,len;
    void get(int n){
        for(int i=2;i<=n;i++){
            if(!v[i]){
                v[i]=2;
                p[++len]=i;
            }
            for(int j=1;j<=len&&i*p[j]<=n;j++){
                v[i*p[j]]=1;
                if(i%p[j]==0)break;
            }
        }
    }
    int main(){
        get(10000000);
        for(int i=1;i<=1000000;i++){
            int a=i,l=-1;
            if(v[i]!=2)continue;
            while(a){
                a/=10;
                ++l;
            }
            a=i;
            for(int k=1;k<=l;k++){
                a=a/10+(a%10)*pow(10,l);
                if(v[a]!=2)goto end;
            }
            ans++;
            end:
                continue;
            }
        cout<<ans;
        return 0;
    } 

    Double-base palindromes

    求$1e6$以下十进制和二进制都是回文数的数,并输出他们的和

    十进制就存下来然后比较

    二进制考虑用bitset存下来然后比较

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 bitset<20>q;
     4 long long ans,tag;
     5 int sum[100];
     6 int main(){
     7     for(register int i=1;i<=1000000;i+=2){
     8         int a=i,len=0;
     9         while(a){
    10             sum[++len]=a%10;
    11             a/=10;
    12         }
    13         for(int k=1;k<=len/2;k++){
    14             if(sum[k]!=sum[len-k+1])goto end;
    15         }
    16         
    17         q=i;
    18         for(tag=19;tag>=0;tag--)
    19             if(q[tag]==1)break;
    20         for(int k=0;k<=tag;k++){
    21             if(q[k]!=q[tag-k])goto end;
    22         }
    23         ans+=i;
    24         end:
    25             continue;
    26     }
    27     cout<<ans;
    28     return 0;
    29 } 

    Pandigital multiples

    一个数分别乘上$1,2,3...n$然后连接起来是一个$1,2,3...9$组成的排列,问当$n>1$时最大的排列是多少

    考虑对于每一个$n$分别考虑这个数可以取值的范围,然后暴力枚举判断即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int ans=123456789;
     4 bool check(int n){
     5     int f=0;
     6     while(n){
     7         f|=1<<(n%10);
     8         n/=10;
     9     }
    10     if(f==(1<<10)-2)return true;
    11     return false;
    12 }
    13 int main()
    14 {
    15     //2
    16     for(int i=5000;i<10000;i++)
    17         if(check(i*100000+i*2))ans=max(ans,i*100000+i*2);
    18     //3
    19     for(int i=100;i<=333;i++)
    20         if(check(i*1000000+i*2000+i*3))ans=max(ans,i*1000000+i*2000+i*3);
    21     //4
    22     for(int i=25;i<=33;i++)
    23         if(check(i*10000000+i*200000+i*3000+i*4))ans=max(ans,i*10000000+i*200000+i*3000+i*4);
    24     //5
    25     for(int i=5;i<=9;i++)
    26         if(check(i*100000000+i*2000000+i*30000+i*400+i*5))ans=max(ans,i*100000000+i*2000000+i*30000+i*400+i*5);
    27     //6
    28     for(int i=3;i<=3;i++)
    29         if(check(i*100000000+i*20000000+i*3000000+i*40000+i*500+i*6))ans=max(ans,i*100000000+i*20000000+i*3000000+i*40000+i*500+i*6);
    30     for(int i=2;i<=2;i++)
    31         if(check(i*100000000+i*20000000+i*3000000+i*400000+i*50000+i*600+i*7))ans=max(ans,i*100000000+i*20000000+i*3000000+i*400000+i*50000+i*600+i*7);
    32     cout<<ans;
    33     return 0;
    34 }

    Integer right triangles

    周长$p$总和小于一千的直角三角形,$p$为何值时有借的数目最多

    由$a^2+b^2=c^2$得到边长的最大值,然后考虑枚举即可

    Champernowne's constant

    把从$1$开始的自然数直接连接起来,求$d_1*d_{10}*d_{100}*d_{1000}*d_{10000}*d_{100000}*d_{1000000}$

    考虑使用stringstream直接暴力搞

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 string S,s;
     4 int main()
     5 {
     6     for(int i=1;S.size()<=1000000;i++){
     7         stringstream ss;
     8         ss<<i;
     9         ss>>s;
    10         S+=s;
    11     }
    12     printf("%d",(S[0]-'0')*(S[9]-'0')*(S[99]-'0')*(S[999]-'0')*(S[9999]-'0')*(S[99999]-'0')*(S[999999]-'0'));
    13     return 0;
    14 }

    Pandigital prime

    让一个$n$位数既是质数又是$1...n$的排列求这个数最大是多少

    考虑答案特殊性,只有当$n=4,7$的时候才会存在,不然会被三整除

    然后全排列从后往前,判断质数

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int len,ans;
     4 int a[100];
     5 inline bool check(int n)
     6 {
     7     if(n==1)return false;
     8     if(n==2||n==3)return true;
     9     if(n%6!=1&&n%6!=5)return false;
    10     for(register int i=5;i*i<=n;i+=6)
    11         if(n%i==0||n%(i+2)==0)return false;
    12     return true;
    13 }
    14 void work(int n){
    15     for(int i=1;i<=n;i++)
    16         a[i]=n-i+1;
    17     do{
    18         int k=0;
    19         for(int i=1;i<=n;i++)
    20             k=(k<<3)+(k<<1)+a[i];
    21         if(check(k)){
    22             cout<<k<<endl;
    23             exit(0);
    24         }
    25     }while(prev_permutation(a+1,a+1+n));
    26 }
    27 int main()
    28 {
    29     
    30     work(7);
    31     work(4);
    32     return 0;
    33 }

    Coded triangle numbers


    三角形数序列的第n项由公式tn = 1/2*n(n+1)给出;因此前十个三角形数是:

    1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...将一个单词的每个字母分别转化为其在字母表中的顺序并相加,我们可以计算出一个单词的值。例如,单词SKY的值就是 19 + 11 + 25 = 55 = t10。如果一个单词的值是一个三角形数,我们就称这个单词为三角形单词。

    在这个16K的文本文件[words.txt]中包含有将近两千个常用英文单词,这其中有多少个三角形单词?

    考虑对于每个单词的值$i*2$然后开个根看看符不符合

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int ans;
     4 char s[10000010];
     5 int main()
     6 {
     7     freopen("1.in.txt","r",stdin);
     8     while(~scanf("%s",s+1)){
     9 
    10         int len=strlen(s+1);
    11         int k=0;
    12         for(int i=1;i<=len;i++)
    13             k+=s[i]-'A'+1;
    14         k*=2;
    15         int a1=(int)sqrt(k);
    16         if(a1*(a1+1)==k)ans++;
    17     }
    18     cout<<ans;
    19     return 0;
    20 }

    Sub-string divisibility

    $next_permutation$搞一搞,暴力加起来

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 unsigned long long sum,ans;
     4 long long a[11];
     5 int main()
     6 {
     7     for(int i=0;i<=9;i++)
     8         a[i]=i;
     9     do{
    10         if((a[1]*100+a[2]*10+a[3])%2==0)
    11         if((a[2]*100+a[3]*10+a[4])%3==0)
    12         if((a[3]*100+a[4]*10+a[5])%5==0)
    13         if((a[4]*100+a[5]*10+a[6])%7==0)
    14         if((a[5]*100+a[6]*10+a[7])%11==0)
    15         if((a[6]*100+a[7]*10+a[8])%13==0)
    16         if((a[7]*100+a[8]*10+a[9])%17==0)
    17         {
    18             ans++;
    19             sum+=(a[0]*1000000000+a[1]*100000000+a[2]*10000000+a[3]*1000000);
    20             sum+=(a[4]*100000+a[5]*10000+a[6]*1000+a[7]*100+a[8]*10+a[9]);
    21         }
    22     }while(next_permutation(a,a+10));
    23     cout<<sum;
    24     return 0;
    25 }

    Pentagon numbers

    五边形数的公式$n(3n-1)/2$

    找出一对五边形数使得他们的差和和也是五边形数,并且使得他们差最小

    考虑枚举,但是有约束,如果外层$i$有$P(i)-P(i-1)>d$那么就退出,内层$P(i)-P(j)>d$也退出然后二分找是否是五边形数,更新答案

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 using namespace std;
     4 inline long long f(int x){
     5     return x*(x*3-1)/2;
     6 }
     7 bool check(int n){
     8     long long l=1,r=n;
     9     while(l<=r){
    10         int mid=(l+r)>>1;
    11         int val=f(mid);
    12         if(val==n)return 1;
    13         if(val<n)l=mid+1;
    14         else r=mid-1;
    15     }
    16     return 0;
    17 }
    18 signed main()
    19 {
    20     int i=2,d=1e9+7;
    21     while(f(i)-f(i-1)<d){
    22         int j=i-1;
    23         while(f(i)-f(j)<d){
    24             if(check(f(i)-f(j))&&check(f(i)+f(j)))
    25                 d=f(i)-f(j);
    26             j--;
    27             if(!j)break;
    28         }
    29         i++;
    30     }
    31     cout<<d;
    32     return 0;
    33 }

    Triangular, pentagonal, and hexagonal

    三角形数 $T(n)=n(n+1)/2$

    五边形数$P(n)=n(3n-1)/2$

    六边形数$H(n)=n(2n-1)$

    有$T(285)=P(165)=H(143)=40775$

    找出下一个这样的

    还是和上一题一样,二分就完事儿了

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 using namespace std;
     4 inline int t(int x){
     5     return x*(x+1)/2;
     6 }
     7 inline int p(int x){
     8     return x*(3*x-1)/2;
     9 }
    10 inline int h(int x){
    11     return x*(2*x-1);
    12 }
    13 inline bool check_p(int x){
    14     int l=1,r=x;
    15     while(l<=r){
    16         int mid=(l+r)>>1;
    17         int val=p(mid);
    18         if(val==x)return 1;
    19         if(val<x)l=mid+1;
    20         else r=mid-1;
    21     }
    22     return 0;
    23 }
    24 inline bool check_h(int x){
    25     int l=1,r=x;
    26     while(l<=r){
    27         int mid=(l+r)>>1;
    28         int val=h(mid);
    29         if(val==x)return 1;
    30         if(val<x)l=mid+1;
    31         else r=mid-1;
    32     }
    33     return 0;
    34 }
    35 signed main()
    36 {
    37     for(int i=286;;i++)
    38         if(check_p(t(i))&&check_h(t(i))){
    39             printf("%lld",t(i));
    40             return 0;
    41         }
    42     return 0;
    43 }

    Goldbach's other conjecture

    **哥德巴赫的另一个猜想**

    克里斯蒂安·哥德巴赫曾经猜想,每个奇合数可以写成一个素数和一个平方的两倍之和。

    $9 = 7 + 2×1^2$
    $15 = 7 + 2×2^2$
    $21 = 3 + 2×3^2$
    $25 = 7 + 2×3^2$
    $27 = 19 + 2×2^2$
    $33 = 31 + 2×1^2$

    最终这个猜想被推翻了。

    最小的不能写成一个素数和一个平方的两倍之和的奇合数是多少?

    在筛素数的时候去再做一次这个操作,遇到没有了就输出

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 using namespace std;
     4 bool v[100010];
     5 int p[10010];
     6 bool used[100010];
     7 int len;
     8 void get(int n){
     9     for(int i=2;;i++){
    10         if(!v[i]){
    11             v[i]=1;
    12             p[++len]=i;
    13             for(int j=1;j<=1000;j++)
    14                 used[p[len]+j*j*2]=1;
    15 //            printf("%lld ",i);
    16         }
    17         else{
    18             if(i%2&&!used[i]){
    19             printf("%d",i);
    20             exit(0);
    21             }
    22         }
    23         for(int j=1;j<=len&&i*p[j]<=n;j++){
    24             v[i*p[j]]=1;
    25             if(i%p[j]==0)break;
    26         }
    27     }
    28 }
    29 signed main()
    30 {
    31     get(10000);
    32     return 0;
    33 }

    Distinct primes factors



    首次出现连续两个数均有两个不同的质因数是在:

    14 = 2 × 7 15 = 3 × 5
    首次出现连续三个数均有三个不同的质因数是在:

    644 = 22 × 7 × 23 645 = 3 × 5 × 43 646 = 2 × 17 × 19
    首次出现连续四个数均有四个不同的质因数时,其中的第一个数是多少?

    $sqrt n$找出质因子种类,然后暴力枚举(很明显相邻四个数不会出现四种质因子相同的情况)

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 using namespace std;
     4 int k[10000001];
     5 int work(int n){
     6     int len=0;
     7     for(int i=2;i*i<=n;i++){
     8         if(n%i==0){
     9             while(n%i==0){
    10                 n/=i;
    11             }
    12             ++len;
    13         }
    14     }
    15     if(n-1)++len;
    16     return len;
    17 }
    18 signed main()
    19 {
    20     for(int i=1;;i++){
    21         k[i]=work(i);
    22         if(i<4)continue;
    23         if(k[i]==k[i-1]&&k[i-1]==k[i-2]&&k[i-2]==k[i-3]&&k[i]==4){
    24             cout<<i-3<<endl;
    25             return 0;
    26         }
    27     }
    28     return 0;
    29 }

    Self powers


    十项的自幂级数求和为 $1^1+2^2+3^3+...+10^{10}=10405071317$

    求如下一千项的自幂级数求和的最后10位数字:$1^1+2^2+...+1000^{1000}$

    long long暴力搞

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const long long p=10000000000;
     4 long long ans,res;
     5 signed main()
     6 {
     7     for(int i=1;i<=1000;i++){
     8         res=i;
     9         for(int j=1;j<i;j++)
    10             (res=res*i,res)%=p;
    11         ans=ans+res;
    12         ans%=p;
    13     }
    14     cout<<ans;
    15     return 0;
    16 }

    Prime permutations

     暴力判断搞一搞

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const long long p=10000000000;
     4 long long ans,res;
     5 inline bool check(int n)
     6 {
     7     if(n==1)return false;
     8     if(n==2||n==3)return true;
     9     if(n%6!=1&&n%6!=5)return false;
    10     for(register int i=5;i*i<=n;i+=6)
    11         if(n%i==0||n%(i+2)==0)return false;
    12     return true;
    13 }
    14 long long work(int x){
    15     long long f=0;
    16     while(x){
    17         f^=1<<(x%10);
    18         x/=10;
    19     }
    20     return f;
    21 }
    22 signed main()
    23 {
    24     for(int i=1000;i<=3339;i++){
    25         if(check(i)&&check(i+3330)&&check(i+6660)){
    26             if(work(i)==work(i+3330)&&work(i+3330)==work(i+6660)){
    27                 cout<<1ll*i*100000000+1ll*(i+3330)*10000+i+6660<<endl;
    28             }
    29         }
    30     }
    31     return 0;
    32 }

    Consecutive prime sum

    首先筛素数,然后枚举长度,枚举起始点,剪剪枝:

    如果最小的几个加起来都超过了,那么退出

    然后如果当前加到了也退出

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 using namespace std;
     4 const int N=1000010;
     5 int v[N],p[N],len,ans;
     6 int sum[N];
     7 void get(int n){
     8     for(int i=2;i<=n;i++){
     9         if(!v[i])v[i]=2,p[++len]=i;
    10         for(int j=1;j<=len&&p[j]*i<=n;j++){
    11             v[p[j]*i]=1;
    12             if(i%p[j]==0)break;
    13         }
    14     }
    15     for(int i=1;i<=len;i++)
    16         sum[i]=sum[i-1]+p[i];
    17 }
    18 signed main(){
    19     get(1000000);
    20     for(int i=0;i<len;i++){
    21         for(int j=1;i+j<=len;j++){
    22             if(sum[i+j]-sum[j]>1000000)break;
    23             if(v[sum[i+j]-sum[j]]==2){
    24                 ans=sum[i+j]-sum[j];
    25                 break;
    26             }
    27         }
    28     }
    29     cout<<ans;
    30     return 0;
    31 }
  • 相关阅读:
    4. 单向循环链表
    3. 单向链表
    2. 队列的实现
    1. 时间复杂度(大O表示法)以及使用python实现栈
    Ubuntu16.04LTS安装集成开发工具IDE: CodeBlocks 和Eclipse-cdt
    Ubuntu16.04搭建各种开发环境的IDE: QT5 , CodeBlocks ,eclipse-cdt, PyCharm
    python2和python3 分别连接MySQL的代码
    面向对象基础
    文件的处理
    离散表(哈希表),深浅拷贝
  • 原文地址:https://www.cnblogs.com/hualian/p/13824871.html
Copyright © 2011-2022 走看看