ZOJ-4029 Now Loading!!!

题干:

给你n个ai和m个pi,求 i = 1 m \sum_{i=1}^{m} (i* j = 1 n \sum_{j=1}^{n} a j log p i a j \lfloor \frac{a_j}{\lceil \log_{p_i}{a_j} \rceil} \rfloor ) % 1 0 9 10^9 的值。
2 p i 1 0 9 2 \le p_i \le 10^{9}
2 a i 1 0 9 2 \le a_i \le 10^{9}

思路:

观察 log p i a j \lfloor \log_{p_i}^{a_j}\rfloor
a i a_i = 1 0 9 10^{9} p i p_i =2时取最大值30
p i p_i = 1 0 9 10^{9} a i a_i =2时取最小值1
又因为是取整,所以分母的范围在[1,30]之间,然后我们可以将分母相同的数放到一起计算,先将 a i a_i 按从小到大排序,我们就可以用二维数组c[i][j]表示分母为i的分子为 a j a_j 的前缀和,
我们对于每次输入 p i p_i ,按 p i k p_i ^ k 求出在a[]数组中的上界 p o s i pos_i ,则 j = 1 n \sum_{j=1}^{n} a j log p i a j \lfloor \frac{a_j}{\lceil \log_{p_i}{a_j} \rceil} \rfloor 就变成了求 j = 1 n \sum_{j=1}^{n} c[k][ p o s i pos_i ](也就是根据分母求不同的前缀和)
注意段错误,前缀和数组(直接用vector最好)、中途的求和、最后的答案用long long型, a i a_i 数组和其他的用int

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const ll mod = 1e9;
int x[200000];
ll c[35][200000]; 
int main()
{
	int t,n,m;
	ll a;
	while(scanf("%d",&t)!=EOF)
	{
		while(t--)
		{
			scanf("%d%d",&n,&m);
			for(int i=1;i<=n;i++){
				scanf("%d",&x[i]);
			}
			sort(x+1,x+n+1);
			for(int i=1;i<=30;i++){
				c[i][0]=0;
				for(int j=1;j<=n;j++){
					c[i][j]=c[i][j-1]+x[j]/i;
				}
			}
			ll ans=0;
			for(int i=1;i<=m;i++){
				scanf("%lld",&a);
				ll  b=a,now=0;
				int last=0,t=0;
	            while(b/a<=x[n])
	            {
	                t++;
	                int pos=upper_bound(x+1,x+1+n,b)-(x+1);
	                now+=(c[t][pos]-c[t][last]+mod)%mod; 
					last=pos;
	                if(b<x[n]) 
						b*=a; 
					else 
						break;
	            }
	            ans=(ans+now%mod*i%mod)%mod;
			}
			printf("%lld\n",ans);
		}
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42279796/article/details/88649503
now