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 }
  • 相关阅读:
    【NOIP 2003】 加分二叉树
    【POJ 1655】 Balancing Act
    【HDU 3613】Best Reward
    【POJ 3461】 Oulipo
    【POJ 2752】 Seek the Name, Seek the Fame
    【POJ 1961】 Period
    【POJ 2406】 Power Strings
    BZOJ3028 食物(生成函数)
    BZOJ5372 PKUSC2018神仙的游戏(NTT)
    BZOJ4836 二元运算(分治FFT)
  • 原文地址:https://www.cnblogs.com/hualian/p/13824871.html
Copyright © 2011-2022 走看看