前面预处理,将分母等于1,2,3。。。时对应的和保存,因为2 的30 次方差不多等于1e9,所以可以开二维数组储存,但是好像可以优化,然后计算时用二分查询,查询出p-p方,p方-p3方。。。。,然后直接调用值加起来就是了,做法比较水,卡内存过了,应该还有其他的方法
#include<cstdio> #include<cmath> #include<cstring> #include<string> #include<cstdlib> #include<algorithm> #include<iostream> #include<queue> #include<stack> #include<map> using namespace std; #define FOU(i,x,y) for(int i=x;i<=y;i++) #define FOD(i,x,y) for(int i=x;i>=y;i--) #define MEM(a,val) memset(a,val,sizeof(a)) #define PI acos(-1.0) const double EXP = 1e-9; typedef long long ll; typedef unsigned long long ull; const int INF = 0x3f3f3f3f; const ll MINF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9; const int N = 5e5+5; ll a[N]; ll Num[32][N]; int main() { ll n,m,p; ll t; scanf("%lld",&t); while(t--) { scanf("%lld%lld",&n,&m); for(ll i=1;i<=n;i++) scanf("%lld",&a[i]); sort(a+1,a+1+n); for(ll i=0;i<=31;i++) { Num[i][0]=0; for(ll j=1;j<=n;j++) { Num[i][j]=a[j]/(i+1)+Num[i][j-1]; } } ll ans=0; for(ll i=1;i<=m;i++) { scanf("%lld",&p); ll cnt=0; ll tmp=1; ll l=0,r; ll x=0; while(1) { tmp *= p; ++cnt; r = (upper_bound(a+1,a+1+n,tmp)-a)-1; x=(x+(Num[cnt-1][r]-Num[cnt-1][l])%mod)%mod; l=r; if(r==n) break; } ans=(ans+(x*i)%mod)%mod; } printf("%lld\n",ans); } return 0; }