ZOJ 4029 Now Loading!!! (字首和加速+二分)
阿新 • • 發佈:2018-12-18
#include<bits/stdc++.h> using namespace std; #define debug puts("YES"); #define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++) #define ll long long #define lrt int l,int r,int rt #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define root l,r,rt #define mst(a,b) memset((a),(b),sizeof(a)) const int maxn =5e5+1000; const int mod=1e9; const int ub=1e6; ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;} ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} /* 題目大意:求字首和加速。 首先把1,pi^2,pi^3,....pi^k, 可以看到k不超過32,就是說對於一個常數, 對於一個pi,每一個i,都有一段字首和類似ai/c+ai+1/c+... 可以預處理下,用二分來查詢ij位置,詳情見程式碼 */ ll a[maxn],p[maxn]; vector<ll> sum[35]; ll n,m; int main() { int t;scanf("%d",&t); while(t--) { scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); for(int i=1;i<=m;i++) scanf("%lld",&p[i]); sort(a+1,a+n+1); for(int i=1;i<35;i++) sum[i].clear(); for(int i=1;i<32;i++) { sum[i].push_back(0); sum[i].push_back(a[1]/i%mod); for(int j=2;j<=n;j++) sum[i].push_back((sum[i][j-1]+a[j]/i)%mod); sum[i].push_back(0); } ll ret=0; for(int i=1;i<=m;i++) { ll pre=1LL,r=p[i],cnt=1LL,ans=0LL; while(pre<=n) { int p2=upper_bound(a+1,a+n+1,r)-a-1; if(p2>=pre) ans=(ans+(sum[cnt][p2]-sum[cnt][pre-1]+mod)%mod)%mod; pre=p2+1,r*=p[i],cnt++; } ret=(ret+1LL*i*ans%mod+mod)%mod; } printf("%lld\n",(ret+mod)%mod); } return 0; }