浙江省省赛 Now Loading!!!

根据题意可以得出分母的范围为:1-30,对于每个a[j]是p^i到p^(i+1)范围内分母都为i+1,对于每个pi最多可以把a[i]数列分为30组,所以枚举每个pi在a[i]中进行二分查找。然后用前缀和处理下a[i]/j。

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const int N=500005+10;
const int MOD=1e9;
#define mem(a,b) memset(a,b,sizeof(a))
int a[N],p[N];
int flag[N],dp[33][N];
void init(int n)
{
    for(int i=1;i<=31;i++)
    {
        dp[i][0]=0;
        for(int j=1;j<=n;j++)
        {
            dp[i][j]=(dp[i][j-1]%MOD+(a[j]/i)%MOD)%MOD;
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        mem(a,0);
        mem(p,0);
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",a+i);
        }
        sort(a+1,a+1+n);
        init(n);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",p+i);
        }
        ll tmp=1,cnt;
        ll sum=0,ans;
        for(int i=1;i<=m;i++)
        {
            tmp=1;
            cnt=0;
            ans=0;
            while(tmp*p[i]<=a[n])
            {
                int l=1,r=n;
                tmp*=p[i];
                int x=upper_bound(a+1,a+1+n,tmp)-a-1;
                flag[++cnt]=x;
            }
            if(flag[cnt]<n)
                flag[++cnt]=n;
            for(int j=1;j<=cnt;j++)
            {
                ans=(ans%MOD+(dp[j][flag[j]]-dp[j][flag[j-1]])%MOD)%MOD;
            }
            sum=(sum+ans*i)%MOD;
        }
        printf("%lld\n",(sum+MOD)%MOD);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pandauncle/article/details/80219521
now