一步之遥
从昏迷中醒来,小明发现自己被关在X星球的废矿车里。
矿车停在平直的废弃的轨道上。
他的面前是两个按钮,分别写着“F”和“B”。
小明突然记起来,这两个按钮可以控制矿车在轨道上前进和后退。
按F,会前进97米。按B会后退127米。
透过昏暗的灯光,小明看到自己前方1米远正好有个监控探头。
他必须设法使得矿车正好停在摄像头的下方,才有机会争取同伴的援助。
或许,通过多次操作F和B可以办到。
矿车上的动力已经不太足,黄色的警示灯在默默闪烁…
每次进行 F 或 B 操作都会消耗一定的能量。
小明飞快地计算,至少要多少次操作,才能把矿车准确地停在前方1米远的地方。
请填写为了达成目标,最少需要操作的次数。
注意,需要提交的是一个整数,不要填写任何无关内容(比如:解释说明等)
#include<bits/stdc++.h>
using namespace std;
int main()
{
int i;
for( i=1;;i++){
if((97*i-1)%127==0)break;
}
cout<<i;//55
cout<<(97*55-1)/127;//42
return 0;
}
答案:97
凑平方数
把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等…
注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。
如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?
注意:需要提交的是一个整数,不要填写多余内容。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5;
vector<ll>nums;
void check(ll x){
int status=0;
if(x==0)status=1;//占0的位置,0的二进制还是0,所以需要赋值1
while(x){
int g=x%10;
if((status&(1<<g))!=0)return ;//一定要加括号
status|=(1<<g);
x/=10;
}
nums.push_back(status);
}
int res=0;
void dfs(int x,int y){
if(y==((1<<10)-1))
{
res++;
return ;
}
for(int i=x;i<nums.size();i++){
if((y&nums[i])==0){//一定要加括号
dfs(i+1,y|nums[i]);
}
}
}
int main(){
for(ll i=0;i<N;i++){//不用担心超过9876543210的数被存入nums中
//因为比9876543210大的数一定存在重复数字,在check函数中就会被过滤掉
check(i*i);
}
dfs(0,0);
cout<<res;
return 0;
}
答案:300
运算符优先级:
() [] -> . * / % + - << >> < <= >= >== != & ^ | && ||
棋子换位
有n个棋子A,n个棋子B,在棋盘上排成一行。
它们中间隔着一个空位,用“.”表示,比如:
AAA.BBB
现在需要所有的A棋子和B棋子交换位置。
移动棋子的规则是:
1. A棋子只能往右边移动,B棋子只能往左边移动。
2. 每个棋子可以移动到相邻的空位。
3. 每个棋子可以跳过相异的一个棋子落入空位(A跳过B或者B跳过A)。
AAA.BBB 可以走法:
移动A ==> AA.ABBB
移动B ==> AAAB.BB
跳走的例子:
AA.ABBB ==> AABA.BB
#include<bits/stdc++.h>
using namespace std;
bool valid(char*data,int k){
if(k<0||k>=strlen(data))return false;
return true;
}
void move(char*data,int from,int to){
data[to]=data[from];
data[from]='.';
}
void f(char*data){
int cnt=0;
while(1){
int flag=0;
int d=0;
int len=strlen(data);
for(int i=0;i<len;i++){
if(data[i]=='.')continue;
if(data[i]=='A')d=1;
if(data[i]=='B')d=-1;
if(valid(data,i+d)&&valid(data,i+d+d)&&
data[i]!=data[i+d]&&data[i+d+d]=='.'){
move(data,i,i+d+d);
cnt++;
printf("%d,%s\n",cnt,data);
flag=1;
break;
}
}
if(flag)continue;
for(int i=0;i<len;i++){
if(data[i]=='.')continue;
if(data[i]=='A')d=1;
if(data[i]=='B')d=-1;
if(valid(data,i+d)&&data[i+d]=='.'){
if(valid(data,i-d)&&valid(data,i+d)&&valid(data,i+d+d)
&&data[i-d]==data[i+d+d])continue;
/*符合移动条件,但是不移动的情况是:该位置的前一个和后面第一个带字母的
位置字母一样,则不移动它,继续向下遍历
因为两个不同字母之间互为跳台,如果中间存在连着的两个字母,则把路堵死
了,两个相同的字母后面的字母则不能跳到前面
跳的意义是为目标而努力,向结果方向走。
而移的意义是为跳提供支点,我移过去是为了我旁边的借助我跳过去,而跳完
之后不能存在两个一样的字母相连,所以推出我这个位置能否移动的条件是
我的前一个字母和后一个字母是否一样,一样则不能移,不一样则可以移动*/
move(data,i,i+d);
cnt++;
printf("%d,%s\n",cnt,data);
flag=1;
break;
}
}
if(flag==0)break;
}
}
int main(){
char data[10]="AAA.BBB";
f(data);
return 0;
}
机器人塔
X星球的机器人表演拉拉队有两种服装,A和B。
他们这次表演的是搭机器人塔。
A
B B
A B A
A A B B
B B B A B
A B A B B A
队内的组塔规则是:
A 只能站在 AA 或 BB 的肩上。
B 只能站在 AB 或 BA 的肩上。
你的任务是帮助拉拉队计算一下,在给定A与B的人数时,可以组成多少种花样的塔。
输入一行两个整数 M 和 N,空格分开(0<M,N<500),分别表示A、B的人数,保证人数合理性。
要求输出一个整数,表示可以产生的花样种数。
例如:
用户输入:
1 2
程序应该输出:
3
再例如:
用户输入:
3 3
程序应该输出:
4
#include<bits/stdc++.h>
using namespace std;
int ans;
int n,m;
int nbit(int num){//求二级制数中有几个数字1
int res=0;
while(num){
num&=(num-1);
res++;
}
return res;
}
bool check(int now,int floor){
int num_a=0;
int num_b=0;
int count=0;
for(int i=floor;i>0;i--){
count=nbit(now);
num_a+=(i-count);
num_b+=count;
now^=(now>>1);//异或运算:相同为零,不同为1
now&=((1<<(i-1))-1);//&1结果不变,控制位数
//左移i-1位后有i位,减1之后才是i-1位,且全是1
if(num_a>n||num_b>m)return false;
}
return num_a==n&&num_b==m;
}
int main(){
cin>>n>>m;
int floor=sqrt((n+m)*2);
for(int i=0;i<(1<<floor);i++){
if(check(i,floor)){
ans++;
}
}
cout<<ans;
return 0;
}
基本思路:先枚举最后一层所有情况,根据异或运算:相同为零,不同为一的特点,用now^(now-1)求出上一层的情况再用num&(num-1)求出1的个数,即累加判断该状态是否符合
求二进制中1的个数
#include<bits/stdc++.h>
using namespace std;
int res1;
int nbit(int x){
while(x){
x&=(x-1);
res1++;
}
return res1;
}
int res2;
int nbit_2(int x){
while(x){
if((x&1)==1){
res2++;
}
x>>=1;
}
return res2;
}
int main(){
int n;
cin>>n;
cout<<nbit(n)<<endl;
cout<<nbit_2(n);
return 0;
}
逻辑运算
0^0=0
1^0=1
0^1=1
1^1=0
异或运算:相同为0,不同为1
0&0=0
1&0=0
0&1=0
1&1=1
与运算:同真为真,一假全假
0|0=0
1|0=1
0|1=1
1|1=1
或运算:一真即为真**
总结:
1) 一步之遥:列方程,暴力枚举x即可求出
2)凑平方数:
1.打表求范围内所有平方数
2.check筛选无重复数字的平方数放入vector中
3.dfs遍历数组中数字
4.&运算标记0~9数字是否重复
3)棋子换位:
首先明确只有跳才是想目标值方向努力,移的目的是为跳提供支点
1.while循环,flag标记,原则是能跳则跳,不能跳才移,移的目的也是为了可以跳
4)机器人塔:
1.循环枚举最后一层情况(以最少的变化换整体的不变)
2.用异或运算确定上面的情况
3.判断该状态是否符合