「The 15th Zhejiang Provincial」F.Now Loading!!!(数论+二分)
描述
传送门:我是传送门
DreamGrid has nn integers a1,a2,…,ana1,a2,…,an. DreamGrid also has mm queries, and each time he would like to know the value of
∑1≤i≤n⌊ai⌈logpai⌉⌋∑1≤i≤n⌊ai⌈logpai⌉⌋for a given number pp, where ⌊x⌋=maxy∈ℤ∣y≤x⌊x⌋=maxy∈Z∣y≤x, ⌈x⌉=miny∈ℤ∣y≥x⌈x⌉=miny∈Z∣y≥x.
输入
There are multiple test cases. The first line of input is an integer TT indicating the number of test cases. For each test case:
The first line contains two integers nn and mm (1≤n,m≤5×1051≤n,m≤5×105) — the number of integers and the number of queries.
The second line contains nn integers a1,a2,…,ana1,a2,…,an (2≤ai≤1092≤ai≤109).
The third line contains mm integers p1,p2,…,pmp1,p2,…,pm (2≤pi≤1092≤pi≤109).
It is guaranteed that neither the sum of all nn nor the sum of all mm exceeds 2×1062×106.
输出
For each test case, output an integer (∑i=1mi⋅zi)mod109(∑i=1mi⋅zi)mod109, where zizi is the answer for the ii-th query.
样例
输入
2
3 2
100 1000 10000
100 10
4 5
2323 223 12312 3
1232 324 2 3 5
输出
11366
45619
思路
这道题的所有题解我全都看了一遍,基本思路大致搞明白,但是卡在最后的一句代码上
1
|
ans = (ans+tmp*j)%mod;
|
最后我发现(∗j∗j)是题目要求的,是时候换个
眼睛脑子了😤刚开始毫无头绪(现在看完别人的题解也是没有头绪···
现场赛之前再回头看一下这个题目吧,这次不写题解了,我现在也实在写不出了来几句···
另外,为什么ZOJ爆内存提示段错误????
代码
/*
* =================================================================
*
* Filename: zoj4029.cpp
*
* Link: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4029
*
* Version: 1.0
* Created: 2018/10/22 21时11分39秒
* Revision: none
* Compiler: g++
*
* Author: 杜宁元 (https://duny31030.top/), duny31030@126.com
* Organization: QLU_浪在ACM
*
* =================================================================
*/
#include <bits/stdc++.h>
using namespace std;
#define clr(a, x) memset(a, x, sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define pre(i,a,n) for(int i=n;i>=a;i--)
#define ll long long
#define max3(a,b,c) fmax(a,fmax(b,c))
#define ios ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int mod = 1e9;
const int N = 5e5+100;
ll a[N];
ll t,n,m,x;
ll sum[N][32];
// 1.对于每一次询问p,枚举分母 i 时,可以找出a中分母等于 i 的那一段
// 预处理前缀和,用于此时直接加。
int main()
{
ios
#ifdef ONLINE_JUDGE
#else
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
scanf("%lld",&t);
while(t--)
{
scanf("%lld %lld",&n,&m);
rep(i,1,n) scanf("%lld",&a[i]);
// rep(i,1,m) scanf("%d",&p[i]);
sort(a+1,a+1+n);
// rep(i,1,n) printf("%lld ",a[i]); printf("\n");
// 打表预处理
for(ll k = 1;k <= 30;k++)
for(ll i = 1;i <= n;i++)
sum[i][k] = sum[i-1][k]+a[i]/k;
ll ans = 0;
for(ll j = 1;j <= m;j++)
{
scanf("%lld",&x);
ll pos;
ll up = x;
ll k = 1;
ll tmp = 0;
for(ll i = 1;i <= n;i = pos+1)
{
// printf("up = %lld\n",up);
pos = i-1;
ll l = i,r = n;
while(l <= r)
{
ll mid = (l+r)>>1;
if(a[mid] <= up)
{
pos = mid;
l = mid+1;
}
else
r = mid-1;
}
tmp = (tmp+sum[pos][k]-sum[i-1][k]+mod)%mod;
k++;
up *= x;
}
//// printf("tmp = %lld j = %lld tmp*j = %lld ans = %lld\n",tmp,j,tmp*j,ans+tmp*j);
ans = (ans+tmp*j)%mod;
}
printf("%lld\n",ans);
}
fclose(stdin);
// fclose(stdout);
return 0;
}