一维数组的查找操作,就是在一维数组中查找有没有某个元素,它的值等于指定的值 x。查找操作的结果可能是一个没找到、找到一个或者找到很多个。常见的查找算法有“顺序”查找和“二分”查找。
顺序查找就是按照从前往后的顺序,将数组中的元素依次与要查找的数 x 进行比较。
二分查找又称“折半”查找,其优点是比较次数少、查找速度快。但是要求数据是递增或递减排序的。
二分查找:改变边界信息,在有序的情况下节省了大量时间+
二分排序:二分通过对半排序,左右融合,在没有序的情况下时间复杂度略小于sort,是绝对的 n*log(n),但其实实用性不大,多用于求逆序对,见下例题
int left = 0,right = n - 1;
int find = n;//find标记找到的位置,初始化为n,表示没找到
while(left <= right){
int mid = (left + right) / 2;
if(a[mid] == x){//找到了,就标记位置,并退出循环
find = mid;
break;
}
if(x < a[mid]) right = mid - 1;//x只能在左半部分
if(a[mid] < x) left = mid + 1; //x只能在右半部分
}
if(find != n) printf("%d\n",find);
else printf("not find\n");
求解a的b次方,for循环一个个算是超时的
所以用数学的方法推论
a的b次方
当b为0时,直接返回1即可
当b为偶数时
就例如2的4次方,详见七上的数学第一章
等于4的2次方
就例如这样,可以用while循环或dfs写
b为奇数时,直接指数减一再反乘系数即可
记得每次%数据
long long s=1;
while(b)
{
if(b%2==1) s=(s%mod*a%mod)%mod;
b=b/2;
a=(a%mod*a%mod)%mod;
}
return s;
int dfs(long long p,long long q)
{
if (q==0) return 1;
else if (q%2==1) return dfs(p,q-1)*p%m;
else
{
long long cnt=dfs(p,q/2)%m;
return cnt*cnt%m;
}
}
没有什么好说的,使用归并排序每一次交换记录逆序对
分成两份排序,交换;再融合与交换
#include
using namespace std;
const int maxn=100010;
int a[maxn],c[maxn];
long long cnt=0;
void work(int l,int r)
{
int mid,tmp,i,j;
if(r>l+1)
{
mid=(l+r)/2;
work(l,mid-1);
work(mid,r);
tmp=l;
for(i=l,j=mid;i<=mid-1&&j<=r;)
{
if(a[i]>a[j])
{
c[tmp++]=a[j++];
// tmp; j;
cnt+=mid-i;
}
else c[tmp++]=a[i++];
}
if(j<=r) for(;j<=r;j++) c[tmp++]=a[j];
else for(;i<=mid-1;i++) c[tmp++]=a[i];
for(i=l;i<=r;i++) a[i]=c[i];
}
else
{
if(a[l]>a[r])
{
swap(a[l],a[r]);
cnt++;
}
}
}
int main()
{
freopen("deseq.in","r",stdin);
freopen("deseq.out","w",stdout);
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
work(1,n);
cout<<cnt;
return 0;
}
看到题目,想到顺推犯人的位置
但前后影响太大
于是逆推总可能情况-两者不相连情况
相减注意负数情况即可
那怎么做出这两个数据呢
这就需要数论实现
每个人都可能在一个位置
所以总情况为m的n次方
那不可能的情况就想小学做的染色问题
是m-1的n-1次方,因为旁边的宗教与自己的宗教不相同
最后快速幂求解取%即可
long long f(long long a,long long b)
{
long long s=1;
while(b)
{
if(b%2==1) s=(s%mod*a%mod)%mod;
b=b/2;
a=(a%mod*a%mod)%mod;
}
return s;
}
int main()
{
freopen("prison.in","r",stdin);
freopen("prison.out","w",stdout);
cin>>m>>n;
x=f(m,n)%mod;
y=m*f(m-1,n-1)%mod;
cout<<(x-y+mod)%mod;
return 0;
}
总之,二分重在实用,可以与多种形式的题目与算法结合,真正的理解和写出二分大有益于代码的学习与码出