1936 反转圈圆
有N盆花围成一圈,编号从0到(N-1)。第i(0<=i<N)号的左边是第((i+1)%N)号,右边是((i-1+N)%N)号。现在可以对任意相邻的两盆花交换位置,经过若干次交换之后,要求第i(0<=i<N)号的右边是第((i+1)%N)号,左边是((i-1+N)%N)号。请问最少要交换几次。
输入
多组测试数据。
第一行给出一个整数T(1<=T<=100),表示测试数据的数目。
接下来T行,每行给出一个整数N(1<=N<=1000000)。
输出
对于每一个测试数据,输出最少的交换次数。
输入样例
样例输入1
2
5
10
输出样例
样例输出1
4
20
最近开始复习算法(应该算是学习算法及其思想),从贪心开始,进入51nod,找到贪心就是这个题,左思右想,用找规律去做。
- 首先发现的是0 4 3 2 1----->0 1 2 3 4,那么,只要挨个的把i和n-i进行交换位置就行了,也就是说,分为奇偶两种情况,n为偶数的时候,中间位置的数不用交换,多次例举并找规律有了ver 1.0的代码
ver 1.0
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,k=1,t;
long long step;
cin>>t;
while(k<=t){
cin>>n;
if(n%2==0){
step=0;
for(int i=1;i<n/2;i++){
int j=n-i;
int minx= min(j-i+1,i+1+n-j);
// cout<<minx<<"\n";
step += 2*minx-3;
}
}
else{
step=0;
for(int i=1;i<=n/2;i++){
int j=n-i;
int minx=min(j-i+1,i+1+n-j);
// cout<<minx<<"\n";
step += 2*minx-3;
}
}
cout<<"::"<<step<<"\n";
k++;
}
return 0;
}
多次检查,兴致勃勃的提交
WTF?!
再来几次检查修改,还是无果,去寻求寝室大佬,发现忽略了一个重要条件,循环的!也就是说
5 4 3 2 1 0 11 10 9 8 7 6
转换为
6 7 8 9 10 11 0 1 2 3 4 5
再寻一次规律,恍然大悟,就有了ver 2.0
ver 2.0
#include<stdio.h>
int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
if(n&1) printf("%lld\n",1LL*(n-1)*(n-1)/4);
else printf("%lld\n",1LL*n*(n-2)/4);
}
}
室友提供的参考里,n为奇数的时候,输出1LL*(n/2)*(n/2),个人觉得不好推,就用了自己规律总结