pos=(pos+1 )%n;
7-8 数组循环左移 (20 分)
本题要求实现一个对数组进行循环左移的简单函数:一个数组a中存有n(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥0)个位置(最前面的m个数循环移至最后面的m个位置)。如果还需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入格式:
输入第1行给出正整数n(≤100)和整数m(≥0);第2行给出n个整数,其间以空格分隔。
输出格式:
在一行中输出循环左移m位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
8 3
1 2 3 4 5 6 7 8
输出样例:
4 5 6 7 8 1 2 3
循环数组写法
#include <bits/stdc++.h>
using namespace std;
int a[105];
int n,m;
void move3(){
for(int i=0;i<m;i++){
for(int j=1;j<=n;j++){
a[j-1]=a[j];
}
a[n]=a[0];
}
for(int i=1;i<=n;i++){
if(i!=n)cout<<a[i]<<" ";
else cout<<a[i];
}
}
void reverse(int l,int r){//将数组l~r段转置 12345
int s=(r-l+1)/2;//转置次数
int temp;
for(int i=0;i<s;i++){//while(r>l)
temp=a[l];
a[l]=a[r];
a[r]=temp;
l++;
r--;
}
}
void move2(){
reverse(1,m);
reverse(m+1,n);
reverse(1,n);
for(int i=1;i<=n;i++){
if(i!=n)cout<<a[i]<<" ";
else cout<<a[i];
}
}
void move1(){// 1 2 3 4 5 6 左移动2个位置
// int j=n-m;//右移动
// j%=n;//之前已经m%=n,n-m<=n m=0时n-m要为0
int j=m+1;//左移
for(int i=0;i<n;i++){
if(i!=n-1)cout<<a[j]<<" ";
else cout<<a[i];
j=(j+1)%n;//循环数组的写法
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
//1、不移动,靠输出
//2、转置1~m,m+1~n,1~n//移动次数最少
//3、普通移动,一个一个地移动
cin>>n>>m;
m=m%n;//如果m大于n,移动n次之后与移动0次没区别
for(int i=1;i<=n;i++){
cin>>a[i];
}
move1();
// move2();
// move3();
return 0;
}
约瑟夫问题
http://noi.openjudge.cn/ch0302/solution/32938506/
#include <bits/stdc++.h>
using namespace std;
int vis[302];//出列的记为1
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;//n只猴子,叫到m号的出列
while(cin>>n>>m){
if(n==0&&m==0)break;
memset(vis,0,sizeof(vis));
int cnt=0;//记录出列的猴子,n-1只
int sign=1;//叫号
int num=0;
//真正的序号 vis[0]必须从下标0开始(不能是1 因为对n求余用到的是0~n-1
while(true){
if(!vis[num]){
if(sign!=m)sign++;//下一只猴子叫号
else{
sign=1;//下次从1叫号
cnt++;//出列
vis[num]=1;
}
}
num=(num+1)%n;//循环的遍历这些猴子 出列的猴子相当于直接跳过
if(cnt==(n-1)&&!vis[num]) {
cout<<num+1<<endl;
break;
}
}
}
return 0;
}