HDU6753&DTOJ4963 2020 Multi-University Training Contest 1 cookies(看星)

58 篇文章 0 订阅
7 篇文章 0 订阅

HDU6753&DTOJ4963 2020 Multi-University Training Contest 1 cookies(看星)

题目

原题

题目描述

Elsa’s elder brother Eric has got n n n cookies in his icebox and each cookie has a special number written on it. Let’s denote the number written on the i t h i^{th} ith cookie by f i f_i fi. f i f_i fi is defined as follows
f_i is defined as this
Here, d i v m e d ( x ) divmed(x) divmed(x) states the median value of divisors of x x x. Let x x x has k k k divisors, then d i v m e d ( x ) divmed(x) divmed(x) is ⌈ k 2 ⌉ t h \left\lceil\frac{k}{2}\right\rceil^{th} 2kth smallest divisor. For example, d i v m e d ( 100 ) = 10 divmed(100)=10 divmed(100)=10, d i v m e d ( 10 ) = 2 divmed(10)=2 divmed(10)=2, d i v m e d ( 1 ) = 1 divmed(1)=1 divmed(1)=1.
One day, Eric opened the icebox and recognized that some of his cookies are missing. His sister Elsa had eaten some of them.
On the first day, she ate cookies that have multiples of p 1 p_1 p1 as indexes and then, re-indexed them starting from 1 1 1 according to their original order. In the same way, she ate cookies with multiples of p i p_i pi as indexes on the i t h i^{th} ith day and re-indexed them. If there were less than p i p_i pi cookies left, she ate none of them. Elsa continued to do so for m days.

As Elsa is keen on math and Eric didn’t want to blame his sister, Eric asked her to find out the number written on the k t h k^{th} kth of remaining cookies.

输入格式

The first line of the input contains an integer T ( 1 ⩽ T ⩽ 60 ) T(1\leqslant T\leqslant 60) T(1T60), denoting the number of test cases. The first line of each test case contains 3 3 3 positive integers n ( 1 ⩽ n ⩽ 1 0 10 ) , m ( 1 ⩽ m ⩽ 1 0 5 ) n(1\leqslant n\leqslant 10^{10}), m(1\leqslant m\leqslant 10^5) n(1n1010),m(1m105)and k ( 1 ⩽ k ⩽ 1 0 10 ) k(1\leqslant k\leqslant 10^{10}) k(1k1010). The next line contains m integers p 1 , p 2 , ⋯ ⋯   , p m ( 1 ⩽ p i ⩽ 1 0 10 ) p_1,p_2,\cdots \cdots,p_m (1\leqslant p_i\leqslant 10^{10}) p1,p2,,pm(1pi1010).

输出格式

For each test case, output one line containing the answer. If the kth cookie doesn’t exist, then output − 1 -1 1 in a single line.

样例

样例输入

2
25 5 9
3 5 8 12 10
25 5 2
3 5 8 12 10

样例输出

31
2

题解

在OI界,有一句名言:“暴力出奇迹,打表出省一”
如果你认为这句话不可能,那么你就错了
你可以点开HDU上的statistic,看看大家的代码长度(已按代码长度从小到大排序):
HDU中的statistic也就是说,最短的代码也有22.5K!!!
这不是打表是什么?
接下来,我们就来看看这道打表题
显然,我们可以用二分或计算,找到第 k k k个饼干初始的位置 K K K,那么问题就在于求 ∑ i = 1 K d i v m e d ( i ) \sum\limits_{i=1}^K divmed(i) i=1Kdivmed(i)的值了
显然,这个东西计算效率很低,因为你肯定需要枚举 1 ∼ K 1\sim \sqrt{K} 1K 之间的所有数,然后计算,效率很低(事实证明很低,我也算不出来)
所以我们可以考虑分段打表!
2500000 2500000 2500000为一段,计算 ∑ i = t + 1 t + 2500000 d i v m e d ( i ) \sum\limits_{i=t+1}^{t+2500000}divmed(i) i=t+1t+2500000divmed(i) 2500000 ∣ t 2500000|t 2500000t),然后把求出来的 4000 4000 4000个值复制到主程序中,就可以了
计算时用类似于挨氏筛质数的方法就可以了
打表代码如下(写题解的时候打的,可能有问题,自己改一下):

const int D=2500000;
long long l,r,a[4010],d[D+10];
int main()
{
    printf("const long long a[4010]={0,");
    for(int t=1;t<=4000;++t){
        a[t]=a[t-1],l=(t-1)*D+1,r=t*D;
        for(long long i=1;i<=100000;i++){
            if(i*i>r) break;
            for(long long L=((l-1)/i)*i+1,j=(r/i)*i;i*i<=j&&L<=j;j-=i) d[j-l]=i;
		}
        for(long long i=l;i<=r;i++) a[t]+=d[i-l];
        printf("%lld,",a[t]);
    }
    printf("};");
}

我自己运行这个程序花了 24 24 24分钟
然后剩下的内容就类似于分块了,如果有剩余的,暴力计算即可
最后还有一个要注意的点,就是为了节省时间,对剩余的部分,如果长度不到 1250000 1250000 1250000,就加上正着算的结果,如果超过 1250000 1250000 1250000,就减去倒着算的结果(这个优化在HDU上可加可不加,但是在DTOJ上不加就会挂,就像我一样,调了一个中午,连饭都没吃……abcde真是太毒瘤啦!
完整代码如下(打表的内容自行填充):

#include<cstdio>
const long long D=2500000,a[]={0,876804130,2440016214,...,190808468780767};
long long n,m,k,ans,flag,l,r,p[100010],d[D+10];
template<class T>inline void read(T &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9')  {f|=(ch=='-');ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
    return;
}
int main()
{
	int T;
	read(T);
	while(T--){
		read(n),read(m),read(k),flag=0;
		for(register int i=1;i<=m;i++) read(p[i]);
		for(register int i=m;i;i--){
			if(p[i]==1){k=1;break;}
			else if(k>n){flag=1;break;}
			else k+=(k-1)/(p[i]-1);
		}
		if(flag||k>n){printf("-1\n");continue;}
		ans=a[k/D];
		if(k%D){
			if(k%D<=D/2){
            	l=(k/D)*D+1,r=k;
            	for(register long long i=1;i<=100000;i++){
            		if(i*i>r) break;
            		for(register long long L=((l-1)/i)*i+1,j=(r/i)*i;i*i<=j&&L<=j;j-=i) d[j-l]=i;
				}
            	for(long long i=l;i<=r;i++) ans+=d[i-l];
			}
			else{
            	ans=a[k/D+1],l=k+1,r=(k/D+1)*D;
            	for(register long long i=1;i<=100000;i++){
            		if(i*i>r) break;
            		for(register long long L=((l-1)/i)*i+1,j=(r/i)*i;i*i<=j&&L<=j;j-=i) d[j-l]=i;
				}
            	for(long long i=l;i<=r;i++) ans-=d[i-l];
			}
		}
		printf("%lld\n",ans);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值