第31题
这一题求200可以由1,2,5,10,20,50,100,200以多少种不同的方式相加而成。
将硬币分别标记为f[1]=1;f[2]=2;f[3]=5;f[4]=10;f[5]=20;f[6]=50;f[7]=100];f[8]=200;
使用
dp[i][j]
表示利用最大面额为f[j]的纸币组成i有多少种方法。
转移就是
dp[i][j]+=∑jk=1dp[i−f[j]][k]
#include<bits/stdc++.h>
using namespace std;
int dp[210][10];
int coin[10]={0,1,2,5,10,20,50,100,200,1000};
int main(){
int n=200;dp[0][1]=1;
for (int i=1;i<=200;i++){
for (int j=1;coin[j]<=i;j++){
for (int k=1;k<=j;k++){
dp[i][j]+=dp[i-coin[j]][k];
}
}
}
for (int i=1;i<=10;i++) dp[200][0]+=dp[200][i];
cout<<dp[200][0]<<endl;
return 0;
}
第32题
这个题要求寻找所有满足条件的数的和。条件为:将数x表示为
x=a∗b
,其中在十进制表示下构成x,a,b三个数的数字中1-9恰好出现一次且没有0。比如
7254=39∗186
。
枚举每个可能的数及其可能的因子,验证即可。这个数不可能超过四位数,因为五位数至少由一个二位数乘三位数或一位数乘四位数得到,这样就有十个数字。
#include<bits/stdc++.h>
using namespace std;
bool check(int i,int j){
int x[10]={0};
int k=i/j,cnt=0;
while(k){
if (x[k%10]) return false;
else x[k%10]=1;
k/=10;cnt++;
}
while(j){
if (x[j%10]) return false;
else x[j%10]=1;
j/=10;cnt++;
}
while(i){
if (x[i%10]) return false;
else x[i%10]=1;
i/=10;cnt++;
}
return cnt==9&&x[0]==0;
}
int main(){
int ans=0;
for (int i=1;i<=9999;i++){
for (int j=2;j*j<=i;j++){
if (i%j==0&&check(i,j)){
ans+=i;
break;
}
}
}
cout<<ans<<endl;
return 0;
}
第33题
这一题对我这个英语渣来说实在难以理解。用了各种翻译工具也没看懂,最后迫不得已翻了一下别人的博客才看懂题目。
这个题目求满足如下格式的分数
ik¯¯jk¯¯¯=ij
或
ik¯¯kj¯¯¯=ij
或
ki¯¯jk¯¯¯=ij
或
ki¯¯kj¯¯¯=ij
,且
i,j,k
都不为零。其中
ik¯¯¯
表示
i∗10+k
这一两位数。
枚举ijk即可
#include<bits/stdc++.h>
using namespace std;
int main(){
int fz=1,fm=1;
for (int i=1;i<=9;i++){
for (int j=i+1;j<=9;j++){
for(int k=i;k<=9;k++){
if (j*(i*10+k)==i*(j*10+k)){
fz*=i;
fm*=j;
}
else if (j*(i*10+k)==i*(k*10+j)){
fz*=i;
fm*=j;
}
else if (j*(k*10+i)==i*(j*10+k)){
fz*=i;
fm*=j;
}
else if (j*(k*10+i)==i*(k*10+j)){
fz*=i;
fm*=j;
}
}
}
}
cout<<fm/__gcd(fz,fm)<<endl;
return 0;
}
第34题
这一题求所有在十进制表示下自身等于各位数字阶乘和的数的和。
考虑到
9!=362880
所以这个数不会超过2,500,000,枚举验证即可。
#include<bits/stdc++.h>
using namespace std;
int f[10];
bool check(int x){
int tmp=x,ans=0;
while(x){
ans+=f[x%10];
x/=10;
}
return ans==tmp;
}
int main(){
f[0]=1;
for (int i=1;i<=9;i++){
f[i]=f[i-1]*i;
}
long long ans=0;
for (int i=10;i<=2500000;i++){
if (check(i)){
ans+=i;
}
}
cout<<ans<<endl;
return 0;
}
第35题
这一题求小于100w的这样的一种素数的和,即不论从哪一位开始读,将所有位依次读完后,得到的数总是素数,例如197,719,971。
先用线性筛求出所有素数,之后对每个素数进行验证。验证时利用线性筛遗留下来的标记数组,可以在
logn
的时间内完成验证。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000000;
int prime[maxn+1],cnt;
int num[maxn+1];
bool check(int x){
int mul=1;
while(mul<=x) mul*=10;
mul/=10;
int tmp=x;
do{
if (tmp%10==0) return false;
tmp=tmp/10+tmp%10*mul;
if (num[tmp]) return false;
}while(tmp!=x);
return true;
}
int main(){
int ans=0;
for(int i=2;i<=maxn;i++){
if(num[i]==0) {
prime[++cnt]=i;
}
for (int j=1;j<=cnt&&i*prime[j]<=maxn;j++){
num[i*prime[j]]=1;
}
}
for(int i=1;i<=cnt;i++){
if (check(prime[i])){
cout<<prime[i]<<endl;
ans++;
}
}
cout<<ans<<endl;
return 0;
}