地产大亨Q先生临终的遗愿是:拿出100万元给X社区的居民抽奖,以稍慰藉心中愧疚。
麻烦的是,他有个很奇怪的要求:
1. 100万元必须被正好分成若干份(不能剩余)。
每份必须是7的若干次方元。
比如:1元, 7元,49元,343元,...
2. 相同金额的份数不能超过5份。
3. 在满足上述要求的情况下,分成的份数越多越好!
请你帮忙计算一下,最多可以分为多少份?
思路:
代码:
#include<cstdio>
int main(){
int n=1000*1000;
int re[100],a=0;
while(n>0){
re[a++]=n%7;
n=n/7;
}
int sum;
for(int i=0;i<a;i++){
sum+=re[i];
}
printf("%d",sum);
}
------------------------------------------[4.2 真题:天平称重]
用天平称重时,我们希望用尽可能少的砝码组合称出尽可能多的重量。
如果只有5个砝码,重量分别是1,3,9,27,81
则它们可以组合称出1到121之间任意整数重量(砝码允许放在左右两个盘中)。
本题目要求编程实现:对用户给定的重量,给出砝码组合方案。
例如:
用户输入:
5
程序输出:
9-3-1
用户输入:
19
程序输出:
27-9+1
要求程序输出的组合总是大数在前小数在后。
可以假设用户的输入的数字符合范围1~121
[4.2 模m运算]
思路:
某个数由3的倍数加减来表示,可以看成某个数的三进制表示,
代码:
#include<cstdio>
#include<cmath>
int main(){
int n,a[100],k=0;
scanf("%d",&n);
while(n>0){
int t=n%3;
if(t==2){
t=-1;
n=n/3+1;
a[k++]=t;
continue;
}
a[k++]=t;
n=n/3;
}
for(int i=k-1;i>=0;i--){
int num=pow(3,i);
if(i==k-1){
printf("%d",num);
}else{
if(a[i]>0){
printf("+%d",num);
}
if(a[i]==0){
continue;
}
if(a[i]<0){
printf("-%d",num);
}
}
}
}
------------------------------------------尼姆堆
有3堆硬币,分别是3,4,5
二人轮流取硬币。
每人每次只能从某一堆上取任意数量。
不能弃权。
取到最后一枚硬币的为赢家。
求先取硬币一方有无必胜的招法。
数论...同余理论
思路:
0010
0101
1100
2 1110
--------
0101
x ^ y ^ x = y
首先对所有数进行亦或,得到sum,然后将sum与每个数亦或,此时得到的数和另外所有数字亦或的结果一样,x ^ x = 0,如果这个数字比之前的数字小,就是合理的。
代码:
#include<cstdio>
void g(int a[],int len){
int sum=0;
for(int i=0;i<len;i++){
sum = sum ^ a[i];
}
for(int i=0;i<len;i++){
int x=sum^a[i];
if(x<a[i]){
printf("%d --> %d
",a[i],x);
}
}
}
int main(){
int a[]={2,5,12,14};
g(a,4);
}
------------------------------------------[4.3 因数分解]
关键:算数基本定理
质因数分解的唯一性
------------------------------------------
求最大公约数与最小公倍数
中国古代...辗转相除法
欧几里得定理:gcd(a,b) = gcd(b,a%b)
最小公倍数 = 乘积 / 最大公约数
代码:
#include<cstdio>
int gcd(int a,int b){
if(b==0) return a;
return gcd(b,a%b);
}
int main(){
int a,b,x;
scanf("%d%d",&a,&b);
printf("gcd:%d
",x=gcd(a,b));
printf("lcm:%d
",a*b/x);
}
------------------------------------------[4.4 真题:一步之遥]
从昏迷中醒来,小明发现自己被关在X星球的废矿车里。
矿车停在平直的废弃的轨道上。
他的面前是两个按钮,分别写着“F”和“B”。
小明突然记起来,这两个按钮可以控制矿车在轨道上前进和后退。
按F,会前进97米。按B会后退127米。
透过昏暗的灯光,小明看到自己前方1米远正好有个监控探头。
他必须设法使得矿车正好停在摄像头的下方,才有机会争取同伴的援助。
或许,通过多次操作F和B可以办到。
矿车上的动力已经不太足,黄色的警示灯在默默闪烁...
每次进行 F 或 B 操作都会消耗一定的能量。
小明飞快地计算,至少要多少次操作,才能把矿车准确地停在前方1米远的地方。
请填写为了达成目标,最少需要操作的次数。
扩展欧几里得定理:
Ax + By = gcd(A,B) 有解
思路:不是太明白
代码:
#include<cstdio>
#include<cmath>
int g(int a,int b,int arr[]){
if(b==0){
arr[0]=1;
arr[1]=0;
return a;
}
int ans = g(b,a%b,arr);
int t=arr[0];
arr[0]=arr[1];
arr[1]=t - a/b * arr[0];
return ans;
}
int main(){
int a[2]={0};
g(97,127,a);
printf("%d",abs(a[0])+abs(a[1]));
}
实用版:
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int main(){
int ans[100],k=0;
for(int i=-1000;i<1000;i++){
for(int j=-1000;j<1000;j++){
if(97*i+127*j==1){
ans[k++]=abs(i)+abs(j);
}
}
}
sort(ans,ans+k);
printf("%d",ans[0]);
}
------------------------------------------[4.5 有理数运算]
------------------------------------------
[4.6 作业:素数表]
第1个素数是2,第2个素数是3,...
求第100002(十万零二)个素数
素数的筛法
思路:
使用循环,判断是否为素数,思路都非常简单,只是如果直接运算的话时间太长,我们进行优化:1、在判断素数的时候,可以将for(int i=2;i<k;i++)改为for(int i=2;i*i<=k;i++),因为一个合数至少可以分解成两个因数,其中一个因数一定小于等于它的开平方,此外,偶数一定不是素数,所以循环的时候,每步加2。
代码:
#include<cstdio>
#include<cmath>
int test(int k){
for(int i=2;i*i<=k;i++){
if(k%i==0){
return 0;
}
}
return 1;
}
int main(){
int count=1,n=3;
while(count!=100002){
if(test(n)){
count++;
}
n+=2;
}
printf("%d",n-2);
}