把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

fxtoi zjzj

题面传送门

\(40\)分:爆搜,此处不作赘述

这道题硬推是很难推的,下面展示一下硬推的过程,以\(f(4,n)\)为例

我们可以根据题目列出一个式子:

\(\sum\limits_{i=1}^{n}{\sum\limits_{j=1}^{n}{\sum\limits_{k=1}^{n}{\sum\limits_{s=1}^{n}{1[i+j+k+s=n]}}}}\)

我们可以使用构造,约去\(s\)

\(\sum\limits_{i=1}^{n}{\sum\limits_{j=1}^{n}{\sum\limits_{k=1}^{n}{1[i+j+k<n]}}}\)

再来:

\(\sum\limits_{i=1}^{n-3}{\sum\limits_{j=1}^{n-i-2}{\sum\limits_{k=1}^{n-i-j-1}{1[i+j+k<n]}}}\)

这步似乎没有什么用,除了减小一点常数以外,但是这个式子等于

\(\sum\limits_{i=1}^{n-3}{\sum\limits_{j=1}^{n-i-2}{\sum\limits_{k=1}^{n-i-j-1}{1}}}\)

读者可以自行证明,接下来

\(\sum\limits_{i=1}^{n-3}{\sum\limits_{j=1}^{n-i-2}{n-i-j-1}}\)

化开

\(\sum\limits_{i=1}^{n-3}{((n-i)(n-i-2)-\sum\limits_{j=1}^{n-i-2}{j+1})}\)

等差数列公式走起

\(\sum\limits_{i=1}^{n-3}{((n-i)(n-i-2)-\frac{(n+1-i)(n-i-2)}{2})}\)

再化开

\(\sum\limits_{i=1}^{n-3}{\frac{1}{2}(n^2-2in+2i^2+i-n-2)}\)

然后套一个\(\sum\limits_{i=1}^{n}{i^2}=\frac{n(n+1)(2n+1)}{6}\)公式就可以推出答案。

可见推\(f(k,n)\)要用到\(\sum\limits_{i=1}^{n}{i^{k-2}}\)的公式,而这个公式是没有通项式的所以我们要换个思路。

可以转换一下模型,\(f(i,k)\)表示在\(k\)个球中间\(k-1\)个空放\(i\)个隔板把这些球分成不同数量的方案数,这明显是\(A_{i}^{k-1}\),但会有重复,所以应该是\(C_{i}^{k-1}\),答案为\(\sum\limits_{i=1}^{n-1}{C_{i}^{n-1}}\)

在这里如果用杨辉三角爆推有\(60\)分。但这个式子也没什么用,因为\(C_{i}^{n-1}\)无法处理,除非用杨辉三角或逆元,当模数是质数是可以用卢卡斯定理(但很可惜,这道题模数不是)但\(\sum\limits_{i=1}^{n-1}{C_{i}^{n-1}}=2^{n-1}\)!!想象一下,对于\(n-1\)个空,每个空对应放与不放两种选择,而所有的情况就对应了所有的组合数。

那么有了这个结论,可以用快速幂优化到\(80\)分(事实证明数据没造好,连普通的乘法都有\(80\)),接下来怎么优化,\(n\leq5\times10^{10^7}\),似乎要用高精,但空间又不够(毒瘤出题人只给了\(4M\)空间(\(275307894a\):还不够吗,足足是\(std\)\(5\)倍!!!)),所以考虑一下模数,我们会发现模数为\(2^{60}-1\),那么\(n=61\)时和\(n=1\)时答案是一样的,所以可以\(\%60\)之后直接做普通乘法。但\(\%60\)又是个问题,高精不可能。

有这样两个定理:\((a\%mod)(b\%mod)=ab \% mod\)\((a\%mod+b\%mod)\%mod=(a+b) \% mod\)

回想一下快读的过程,只有\(\times\)\(+\)两种,那么直接可以用快读的方法过掉,最大用时\(497ms\),(\(275307894a\):你看,时限还是\(std\)\(2\)倍呢)

代码实现:

#include<cstdio>
using namespace std;
long long ans=1,tot,pus,n,x;
char s;
int main(){
	
	register int i;
	s=getchar();
	while(s<'0'||s>'9') s=getchar();
	while(s>='0'&&s<='9') x=((x<<3)+(x<<1)+(s^48))%60,s=getchar();
	x=(x+59)%60;
	for(i=1;i<=x;i++) ans*=2;
	printf("%lld\n",ans); 
}
posted @ 2020-11-03 18:41  275307894a  阅读(82)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end