欧拉之路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 }