- 快速幂取余数(模板)
运算符:
& :通常用于二进制取位,x&1判断x的末尾是否为1,若x为奇数则返回1,否则返回0。
‘>>: 右移操作,相当于乘于2,相对的<< 左移操作为除于2(比直接乘于2和除于2要快)
快速幂(a^b);
当b为偶数时:a ^ b = a ^ (b/2) +*a^(b/2) ; (例如:2^6 = 2^3 * 2^3 )
当b为奇数时:a ^ b = a * a^(b/2) ; (例如 : 2 ^ 5 = 2 * 2 ^ 4)
快速幂取模:
因为某个因子取余后相乘再取余余数保持不变,所以有以下公式
(a ^ b)modc = (a mod c) ^ b mod c(但是在c太大的情况下可能会超时,所以又有了以下的公式)
#include <cstdio>
int main(){
long long a , b , c ;
scanf ("%lld%lld%lld",&a,&b,&c) ;
long long ans = 1 ;
printf("%lld^%lld mod %lld=",a,b,c);
a %= c ;
while(b){
if (b & 1 == 1) //若b为奇数
ans = (ans*a) %c ;
b = b >> 1 ; //右移,相当于除于2
a = (a*a) % c ;
}
ans %= c ;
printf ("%lld\n",ans) ;
return 0 ;
}
- p1010 幂次方(解见注释)
#include <cstdio>
#include <cmath>
void f(int x){
for (int i = 14 ; i >= 0 ; i --){
if (pow(2,i) <= x){ //找出最大的pow(2,i) <= x
if (i == 0) printf ("2(0)") ; //不用再分解了,直接打印出来
else if (i == 1) printf ("2") ; //为2(1)直接输出2
else{
printf ("2(") ;
f(i) ; //继续递归指数
printf (")") ;
}
x -= pow(2,i) ;
if(x != 0) printf ("+") ;
}
}
}
int main(){
int n ;
scanf ("%d",&n) ;
f(n) ;
return 0 ;
}
- p1908 逆序对(归并排序)
一个数组的归并排序,先将一个数组二分,一直分到只有一个元素然后开始合并,
图解来源:https://www.jianshu.com/p/33cffa1ce613
每次划分完左右区间后,左边的区间一定已经是顺序的了,这时候只要统计右边区间会与左边区间产生多少对逆序对即可;
例如:(左区间(i):5,6,10)(右区间(j):3,4,12)
合并时:
1、5>3 , 产生了逆序对而且排在5后面未被合并的数都比3大,即一共有三对逆序对(左区间长度 - 当前左区间元素下标 + 1);
2、5>4同样产生3对逆序对,然后一直对比合并下去。
#include <cstdio>
typedef long long ll ;
const int N = 5e5 + 10 ;
int f[N] , g[N] ;
long long ans ;
int inline read(){
int f = 1 , x = 0 ;
char ch = getchar() ;
while(ch < '0' || ch > '9'){
if (ch == '-') f = -1 ;
ch = getchar() ;
}
while(ch >= '0' && ch <= '9'){
x = (x<<3) + (x<<1) + (ch^48) ;
ch = getchar() ;
}
return f*x ;
}
void inline print(long long x){
char num[200] ;
if (x < 0){
putchar('-') ;
x = -x ;
}
ll len = -1 ;
while(x){
num[++len] = x%10 + '0' ;
x /= 10 ;
}
len ++ ;
while(len >= 0) putchar(num[--len]) ;
}
void merge(int l , int r){
if (l == r)
return ;
int mid = (l+r)/2 , i = l , j = mid+1 , index = l ;
merge(l,mid) ;
merge(mid+1,r) ;
while(i <= mid && j <= r){
if (f[i] <= f[j]) g[index++] = f[i++] ;
else{
g[index++] = f[j++] ;
ans = ans + mid - i + 1 ;
}
}
while(i <= mid) g[index++] = f[i++] ;
while(j <= r) g[index++] = f[j++] ;
for (int k = l ; k <= r ; k ++) f[k] = g[k] ;
}
int main(){
int n = read() ;
for (int i = 1 ; i <= n ; ++i)
f[i] = read() ;
merge(1,n) ;
print(ans) ;
return 0 ;
}