原题解链接:https://ac.nowcoder.com/discuss/181037
此题为送温暖题目。。
把所有的数字转换为三进制,对于每个卡片都是形如的形式
所以为的形式,共有位
然后考虑当第位上为的时候,表示这一位上需要选个 的卡片,同样,为时需要个,为时只需一个。
当需要个时,有两种选择,其他的都只有一种选择。
又因为的形式是
我们从枚举到,只需考虑哪些位置上面是即可。
如果当前有个位置为那么共有 种情况,且贡献为 ,然后其他位置可以为,也可以为。所以贡献为 。所以当前的贡献就是
所以最终答案为
将 提出来。那就是 。
用二项式定理合并那个,其实就是 ,所以最终答案为 。
注意到当时是不符合题目要求的,所以要减去他的贡献。
所以真正的最后答案是
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <cassert>
typedef long long ll;
char s[100100];
ll Mul(ll a, ll b, ll m){
ll rnt = 0;
a %= m;
while(b){
if(b & 1) rnt = (rnt + a) % m;
a = (a << 1) % m;
b >>= 1;
}
return rnt;
}
ll Pow(ll a, ll n, ll m){
if(n == 1) return a;
else{
ll rnt = Pow(a, n / 2, m);
rnt = Mul(rnt, rnt, m);
if(n & 1) rnt = Mul(a, rnt, m);
return rnt;
}
return 0;
}
int main(){
int T; scanf("%d", &T);
while(T--){
ll m;
scanf("%s%lld", s, &m);
ll phi = m, t = m;
for(ll i = 2; i <= t / i; ++i)
if(t % i == 0){
phi = phi / i * (i - 1);
while(t % i == 0) t /= i;
}
if(t > 1)
phi = phi / t * (t - 1);
ll res = 0; bool flag = false;
for(int i = 0; s[i]; ++i){
res = res * 10 + s[i] - '0';
if(res >= phi) res %= phi, flag = true;
}
ll ans = (Pow(4 % m, res + flag * phi, m) - 1 + m) % m;
printf("%lld\n", ans);
}
return 0;
}