河北省赛的题https://ac.nowcoder.com/acm/contest/903/B
记得现场赛的时候这道题卡死 神仙队友从逆元到二分神操作
本来神仙出题人Icebound想把这道题数据开到10^18的
说实话我还不知道10^18该咋搞
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll poww(ll base, ll n, int p){//快速幂
ll ans = 1;
while(n){
if(n & 1) ans = (ans * base) % p;
base = (base * base) % p;
n >>= 1;
}
return ans;
}
ll sum(int q, int n, int p){//二分求和
if(q == 0) return 0;
if(n == 1) return q;
if(n & 1) // = sum(1 ~ n/2) + q^(n/2 + 1) + q^(n/2 + 1) * sum(1 ~ n/2)
return ((1 + poww(q, n / 2 + 1, p)) * sum(q, n / 2, p) + poww(q, n / 2 + 1, p)) % p;
else // = sum(1 ~ n/2) + q^(n/2) * sum(1 ~ n/2)
return ((1 + poww(q, n / 2, p)) * sum(q, n / 2, p)) % p;
}
int main()
{
int T, n, q, p;
scanf("%d", &T);
while(T--){
scanf("%d%d%d", &q, &n, &p);
printf("%lld\n", sum(q, n, p));
}
return 0;
}
还有种解法
#include <bits/stdc++.h>
#define ll __int128
using namespace std;
template <class T> void read(T &num){
char c; bool is_minus = false;
while((c = getchar())){
if(c >= '0' && c <= '9'){
num = c - '0';
while((c = getchar()) && c >= '0' && c <= '9') num = num * 10 + c - '0';
ungetc(c, stdin);
if(is_minus) num = -num;
break;
}
else if(c == '-') is_minus = true;
}
}
void _print(__int128 x){
if(x > 9) _print(x/10);
putchar(x%10 + '0');
}
ll quickpoww(ll base, ll n, ll MOD){
ll ans = 1;
while(n){
if(n & 1) ans = ans * base % MOD;
base = base * base % MOD;
n >>= 1;
}
return ans;
}
void solve(){
ll q, n, p;
read(q); read(n), read(p);
if(q == 1) {_print(n % p); printf("\n");}
else {
ll Mod = p * (q - 1);
ll t = quickpoww(q, n + 1, Mod) - q;
while(t < 0) t += Mod;
_print(t % Mod / (q - 1));
printf("\n");
}
}
int main(){
int T; scanf("%d", &T);
while(T--) solve();
}