#include <iostream> #include <stdio.h> #include <string.h> #include <queue> #include <vector> #include <math.h> using namespace std; long long int QPow(long long int a,long long int x){ if(x == 0){return 1;} if(x == 1){return a;} long long int ans = QPow(a,x / 2); if(x % 2 == 0){return ans * ans;} return ans * ans * a; } int main(){ long long int a,b; while(scanf("%lld%lld",&a,&b) != EOF){ long long int ans = QPow(a,b); printf("%lld ",ans); } return 0; }
算法时间复杂度O(logN)。
牛客网WannaFly挑战赛11.B——白兔的式子
链接:https://www.nowcoder.com/acm/contest/73/B
来源:牛客网
题目描述
已知f[1][1]=1,f[i][j]=a*f[i-1][j]+b*f[i-1][j-1](i>=2,1<=j<=i)。
对于其他情况f[i][j]=0
有T组询问,每次给出a,b,n,m,求f[n][m] mod (998244353)
输入描述:
第一行为一个整数T,表示询问个数。
接下来一共T行,每行四个整数a,b,n,m。
输出描述:
一共T行,每行一个整数,表示f[n][m] mod (998244353)
示例1
输入
2 2 3 3 3 3 1 4 1
输出
9 27
备注:
T<=100000
1<=m<=n<=100000
0<=a,b<=109
同余除法,求逆元,费马小定理,快速幂,阶乘预处理
费马小定理:一个数a,一个质数p。a的逆元是a^(p - 2)。
AC代码:
#include<iostream> #include<algorithm> #include<string> #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<cstring> #include<math.h> using namespace std; long long int Mod = 998244353; long long int A[200050]; long long int P[200050]; long long int QPow(long long int a,long long int x){ if(x == 0){return 1;} if(x == 1){return a;} long long int ans = QPow(a,x / 2); if(x % 2 == 0){return ans * ans % Mod;} return ans * ans % Mod * a % Mod; } void init(){ A[0] = 1; A[1] = 1; for(int i = 2;i <= 200000;i ++){ A[i] = i * A[i - 1] % Mod; } P[0] = 1; P[100000] = QPow(A[100000],Mod - 2); for(int i = 99999;i >= 1;i --){ P[i] = P[i + 1] * (i + 1) % Mod; } } int main() { int T; init(); scanf("%d",&T); while(T --){ long long int a,b,n,m; scanf("%lld%lld%lld%lld",&a,&b,&n,&m); if(m > n){printf("0 ");} else{ long long int ans = A[n - 1] * P[m - 1] % Mod * P[n - m] % Mod * QPow(a,n - m) % Mod * QPow(b,m - 1) % Mod; printf("%lld ",ans); } /* printf("%lld ",A[n - 1]); printf("%lld ",QPow(A[m - 1],Mod - 2)); printf("%lld ",QPow(A[n - m],Mod - 2)); printf("%lld ",QPow(a,n - m)); printf("%lld ",QPow(b,m - 1)); */ } return 0; }
提交的过程中,一开始将ans分成两部分再乘到一起,WA了无数发,后来放到一起就神奇的过了。不知道为啥= =
Hrbust 1140
题目大意:
给a,b(2000000000以内),求出a^b在进行策略。
策略为将所有数字加到一起,循环至一位数。
如12345 = 1+2+3+4+5 = 15 = 1+6 = 7。
题意分析:
矩阵快速幂无需多说,重要的是该模多少。
有一个推论 设 abcde为一个整数,a+b+c+d+e = n,则n%9 = abcde % 9。
推理如下:
a + b + c + d + e = 9999a + a + 999b + b + 99c + c + 9d + d + e = abcde。
AC代码:
#include <iostream> #include <stdio.h> #include <string.h> #include <queue> #include <vector> #include <math.h> #define llt long long using namespace std; long long int Mod = 9; long long int QPow(long long int a,long long int x){ if(x == 0){return 1;} if(x == 1){return a;} long long int ans = QPow(a,x / 2); if(x % 2 == 0){return ((ans % Mod) * (ans % Mod)) % Mod;} return ((ans % Mod) * (ans % Mod) % Mod * a % Mod) % Mod; } int main(){ long long int a,b; while(scanf("%lld%lld",&a,&b) != EOF){ long long int ans = QPow(a,b); if(a == 0){ans = 0;} else if(ans == 0){ans = 9;} printf("%lld ",ans); } return 0; }
石油大学oj 6016
题目要求 给n(3,1e9),k(3,1e6),求C(n,k) + ... + C(n,n)。
因为k<<n,应求2^n - C(n,0) - C(n,1) - ... - C(n,k - 1)。
主要坑点在于如何处理负数,加上modd再模一次即可。
#include<bits/stdc++.h> using namespace std; long long int ans = 1; long long int modd = 1e9 + 7; long long int QPow(long long int a,long long int x){ if(x == 0){return 1;} if(x == 1){return a;} long long int ans = QPow(a,x / 2); if(x % 2 == 0){return ans * ans % modd;} return ans * ans % modd * a % modd; } long long int _p(long long int x){ return QPow(x,modd - 2); } void C(long long int n,long long int k){ long long int t1 = n; long long int t2 = 1; long long int a = n; long long int b = 1; for(long long int i = 1;i < k;i ++){ ans = (ans - a * _p(b) % modd + modd) % modd; //printf("A %lld ",ans); //printf("M %lld ",a * _p(b) % modd); t1 --;t2 ++; a = a * t1 % modd; b = b * t2 % modd; //printf("a %lld b %lld ",a,b); } } int main(){ long long int n,k; while(scanf("%lld%lld",&n,&k)!=EOF){ if(k > n){printf("0 ");continue;} ans = QPow(2,n) - 1; C(n,k); printf("%lld ",ans); } return 0; }