传送门:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1245
思路:这题并不难很快就搞出来了。。。
首先对于一个组合数
(nm)
我们怎样计算它的贡献呢?
实际上它会对
∑+∞i=1⌊npi⌋−⌊mpi⌋−⌊n−mpi⌋
贡献1
然而不要被吓到了,观察这个等式,发现对于每个
i
至多贡献1,这样最大的幂指数是
再考虑什么时候会做出贡献呢?
很明显当
n
那么我们将
n
按
设
f[i][j][0/1]
从低位到高位到第
i
位,目前贡献为
竟然不用枚举什么
复杂度:
O(Tlog2pn)
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#define C 65
using namespace std;
typedef long long LL;
LL M,P,Max_,loc[C],f[C][C][2];
void init(){
scanf("%lld%lld",&M,&P);
Max_ = 0;
while (M){
loc[Max_++] = M % P;
M /= P;
}
}
void DO_IT(){
LL x;
memset(f,0,sizeof(f));
f[0][0][0] = loc[0] + 1;
f[0][1][1] = P - 1 - loc[0];
for (int i = 0;i < Max_ - 1; ++i){
x = loc[i + 1];
for (int j = 0;j < Max_; ++j){
f[i + 1][j][0] += (x + 1) * f[i][j][0] + x * f[i][j][1];
f[i + 1][j + 1][1] += (P - x - 1) * f[i][j][0] + (P - x) * f[i][j][1];
}
}
LL j = Max_;
while (!f[Max_ - 1][j - 1][0]) --j;
for (int i = 0;i < j; ++i) printf("%lld ",f[Max_ - 1][i][0]);
puts("");
}
int main(){
int T;
scanf("%d",&T);
while (T--){
init();
DO_IT(); }
return 0;
}
总结: