本文主要是介绍牛客练习赛15-C:吉姆的奇思妙想(三分),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
链接:https://www.nowcoder.com/acm/contest/83/C
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
当吉姆刷到 wannafly挑战赛12 F.小H和圣诞树 这题时,颇为震惊,因为这是他第一次在wannafly挑战赛上看到作者提供的解答的时间复杂度的式子里含有根号的题目,于是吉姆就开始在网络上搜寻拥有类似时间复杂度解法的问题,并且看到了以下这题:
给你一个有 N 个点 M 条边的无向简单图,请算算此图中有几个三角形。我们称无序的三个点 x,y,z 为三角形,若且唯若 (x,y)、(y,z)、(x,z) 都是此图上的边。吉姆 想了这个问题七天七夜后,他发现了一件事情:
(1) 对于任一个度数为 d 的点,我们可以用 O(d 2) 的时间复杂度来计算有多少三角形包含这该点。
吉姆 又想了这个问题七天七夜后,他又发现了一件事情:
(2) 对于任一个点,我们可以用 O(M) 的时间复杂度来计算有多少三角形包含该点。
吉姆又再想了这个问题十四天十四夜后,他忽然想到:
(3) 不如就把 (1) 和 (2) 的算法结合在一起!找一个恰当的整数s 若一个点度数小于等于s,就使用(1),否则就使用(2),经过缜密的时间复杂度分析,发现这么做的时间复杂度会是
但这个 s 的值究竟要设为多少呢?这就和 (1) 与 (2) 两种方法的执行时间的常系数有关了。
于是,吉姆为了透彻了解这个问题,就假定(1) 和(2) 的常系数分别是a 与b,这意思是:对于一个度数为d 的点,若使用(1),程式的执行时间和a×d 2 成正比;若使用(2),程式的执行时间则和b×M 成正比。
对于一个给定的图,吉姆想要知道对于不同的 a,b,s 的值要取多少比较好,并且求出 s 为该值时程式所需的执行时间!
(deg i 和 freq i 对应到 Background 里提到的问题的意思就是:度数为 deg i 的点 有 freq i 个。)
你要回答 Q 个问题,第 i 个问题会给你 2 个正整数 a i, b i,请找到一个整数 s 使得以下式子(E i) 的值最小:
(此式就是 Background 里提到的程式执行时间的估计函数)
输入描述:
输入共有 1+L+1+Q 行。第一行有有两个正整数 M,L。接下来的 L 行中的第 i 行有两个正整数 degi 和 freqi。下一行有一个正整数 Q。最后 Q 行中的第 i 行有两个正整数 ai, bi。
输出描述:
对于每个询问都输出一行包含一个整数,代表式子 Ei 的最小值。
输入
5 4 1 1 2 1 3 1 4 1 5 1 1 3 2 2000 1 1 2000 2000 2000
输出
15 33 20 30 30000
说明
取 s=2 将會有 E1 的最小值:12×1+22×1+5×1+5×1=15。
备注:
1≤M≤1010,1≤L≤2×105,1≤degi,freqi≤1010,1≤Q≤5×104,1≤ai,bi≤2×103,对于所有 1≤i<L,都有 degi<degi+1
思路:分析E的那个式子,可以发现随着s的变化,E要么单调,要么先递减后递增。于是可以用三分,还要预处理一下。不过中途会爆long long,然后调试1个多小时,还是WA,果然还是太菜。没办法只有用JAVA写了。
import java.util.*;
import java.math.*;
public class Main {static BigInteger pre[]=new BigInteger[200010];static BigInteger suf[]=new BigInteger[200010];static BigInteger A[]=new BigInteger[200010];static BigInteger B[]=new BigInteger[200010];static int n;public static BigInteger check(int dx,BigInteger a,BigInteger b){return a.multiply(pre[dx]).add(b.multiply(suf[dx+1]));}public static void main(String args[]){Scanner cin=new Scanner(System.in);BigInteger M=cin.nextBigInteger();n=cin.nextInt();for(int i=1;i<=n;i++){A[i]=cin.nextBigInteger();B[i]=cin.nextBigInteger();}pre[0]=BigInteger.ZERO;suf[n+1]=BigInteger.ZERO;for(int i=1;i<=n;i++){pre[i]=A[i].multiply(A[i].multiply(B[i]));if(i>1)pre[i]=pre[i].add(pre[i-1]);}for(int i=n;i>=1;i--){suf[i]=M.multiply(B[i]);if(i<n)suf[i]=suf[i].add(suf[i+1]);}int T=cin.nextInt();while((T--)>0){BigInteger a=cin.nextBigInteger();BigInteger b=cin.nextBigInteger();int l=0,r=n;while(r-1>l){int m=(l+r)/2;int mm=(m+r)/2;if(check(mm,a,b).compareTo(check(m,a,b))<0)l=m;else r=mm;}BigInteger ans=check(l,a,b);for(int i=l-4;i<=l+4;i++)if(i>=0&&i<=n&&ans.compareTo(check(i,a,b))>0)ans=check(i,a,b);System.out.println(ans);}}
}
这篇关于牛客练习赛15-C:吉姆的奇思妙想(三分)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!