ZOJ 4029 Now Loading!!!(前缀和+二分)

Now Loading!!!

Time Limit: 1 Second      Memory Limit: 131072 KB

DreamGrid has integers . DreamGrid also has queries, and each time he would like to know the value of

for a given number , where , .

Input

There are multiple test cases. The first line of input is an integer indicating the number of test cases. For each test case:

The first line contains two integers and () -- the number of integers and the number of queries.

The second line contains integers ().

The third line contains integers ().

It is guaranteed that neither the sum of all nor the sum of all exceeds .

Output

For each test case, output an integer , where is the answer for the -th query.

Sample Input

2
3 2
100 1000 10000
100 10
4 5
2323 223 12312 3
1232 324 2 3 5

Sample Output

11366
45619

Author: LIN, Xi

Source: The 15th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple

思路:题意很容易看懂,但是暴力的话肯定超时。仔细看的话,可以发现因为分母是向上取整的,再根据题目给的数据范围我们可以确定分母一定在1~30之间。并且我们可以知道如果a[i]的范围在(p^(i-1),p^i]之间的话分母就为i,这样子的话先从小到大把数组排好序,之后就可以二分查找p^i(p^i<=a[n])在数组中的位置,这样子数组就能被分割成一段一段的,每一段当中的数分母都是相同的。我们通过预处理好a[i]/k(1<=i<=n,1<=k<=30)的前缀和,就能很快的计算出来了。

debug了好久才发现最后输出答案的时候要(sum+mod)%mod,sum不可能为负数不知为啥要加上mod再取模,有大佬知道吗TAT

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=500005;
const int mod=1e9;
int a[maxn],p[maxn],k[35][maxn];
int n,m;
void init()
{
    for(int i=1;i<=30;i++)
    {
        k[i][0]=0;
        for(int j=1;j<=n;j++)
        {
            k[i][j]=(k[i][j-1]+(a[j]/i))%mod;
        }
    }
}
int main()
{
    int t,flag[maxn],cnt;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        init();
        for(int i=1;i<=m;i++)
            scanf("%d",&p[i]);
        ll sum=0,ans;
        ll temp;
        for(int i=1;i<=m;i++)
        {
            temp=1;
            cnt=0;
            ans=0;
            while(temp*p[i]<=a[n])
            {
                temp*=p[i];
                int l=1,r=n;
                while(l<=r)
                {
                    int mid=(l+r)/2;
                    if(a[mid]<=temp)
                        l=mid+1;
                    else
                        r=mid-1;
                }
                flag[++cnt]=r;
            }
            if(flag[cnt]

你可能感兴趣的:(思考题)