875 快速幂
快速幂就是将a^k看做是a^2^0和a^2^1……相乘。(相邻两个数是平方关系)
巧妙的是这个时候k就是多个2^n的组合,也就是可以二进制表示。
所以就可以用k的二进制某一位是否为1,判断最后的结果是否乘以a^2^n。
错误点:权值不用初始化直接使用a,每次循环将a平方。
#include<bits/stdc++.h>
using namespace std;
//875 快速幂
typedef long long LL;
LL a,b,p;
int n;
LL qum(int a,int n,int p)
{LL ans=1;while(n){if(n&1){ans=ans*a%p;}a=(LL)a*a%p;n>>=1;}return ans;
}
int main()
{int n;cin>>n;while(n--){cin>>a>>b>>p;cout<<qum(a,b,p)<<endl;}}
3625 幂次方
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
//3625 幂次方
LL a,b,p;
LL qum(LL a,LL b)
{LL ans=1;while(b){if(b&1){ans=ans*a%233333;}b>>=1;a=a*a%233333;}return ans;
}int main()
{cin>>a>>b;p=23333;cout<<qum(a,b)<<endl;
}
876. 快速幂求逆元(算法基础课)
a模p的逆元是a的(p-2)次方。
4496. 吃水果
不理解为什么前面还要乘以一个m.
先在n-1个点里面找出k个点。每一个点只有m-1种选择。
所以(m-1)^k*C(n-1,k)再乘以m
错误点:有较大取模的题目,要注意每一步运算都要考虑取模,否则运算会越界
#include<bits/stdc++.h>
using namespace std;
//885 求组合数
typedef long long LL;
const int N=2010;
LL n,m,k,p=998244353;
LL f[N][N];
//快速幂
LL qum(LL a,LL k)
{LL ans=1;while(k){if(k&1){ans=ans*a%p;}k>>=1;a=a*a%p;}return ans;
}//求组合数
void zuhe()
{for(int i=0;i<n;i++){for(int j=0;j<=i;j++){if(!j){f[i][j]=1;}else{f[i][j]=(f[i-1][j]+f[i-1][j-1])%p;}}}
}int main()
{cin>>n>>m>>k;zuhe();LL ans=(f[n-1][k]*m)%p;ans=(ans*qum((m-1),k))%p;cout<<ans<<endl;
}
885 求组合数I
用的逆元法求组合数。注意求某个阶乘mod 某个数的逆,可以用递推地乘以当前数的逆。
#include<bits/stdc++.h>
using namespace std;
//885 求组合数
typedef long long LL;
const int N=2010;
LL n,m,k,p=1e9+7;
LL fact[N],infact[N];
//885 求组合数
//快速幂(求逆)
LL qum(LL a,LL k)
{LL ans=1;while(k){if(k&1){ans=ans*a%p;}k>>=1;a=a*a%p;}return ans;
}//逆元法求组合数
void zuhe()
{infact[0]=1;fact[0]=1;for(int i=1;i<=N;i++){fact[i]=(fact[i-1]*i)%p;//cout<<"非逆"<<fact[a]<<endlinfact[i]=infact[i-1]*qum(i,p-2)%p;}
}int main()
{cin>>n;LL a,b;zuhe();while(n--){cin>>a>>b;LL ans=(fact[a]*infact[a-b])%p;ans=(ans*infact[b])%p;//cout<<"逆"<<infact[a-b]<<endl;cout<<ans<<endl;}}