40 40 40分:爆搜,此处不作赘述
这道题硬推是很难推的,下面展示一下硬推的过程,以 f ( 4 , n ) f(4,n) f(4,n)为例
我们可以根据题目列出一个式子:
∑ i = 1 n ∑ j = 1 n ∑ k = 1 n ∑ s = 1 n 1 [ i + j + k + s = 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]}}}} i=1∑nj=1∑nk=1∑ns=1∑n1[i+j+k+s=n]
我们可以使用构造,约去 s s s
∑ i = 1 n ∑ j = 1 n ∑ k = 1 n 1 [ i + j + k < n ] \sum\limits_{i=1}^{n}{\sum\limits_{j=1}^{n}{\sum\limits_{k=1}^{n}{1[i+j+k<n]}}} i=1∑nj=1∑nk=1∑n1[i+j+k<n]
再来:
∑ i = 1 n − 3 ∑ j = 1 n − i − 2 ∑ 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[i+j+k<n]}}} i=1∑n−3j=1∑n−i−2k=1∑n−i−j−11[i+j+k<n]
这步似乎没有什么用,除了减小一点常数以外,但是这个式子等于
∑ i = 1 n − 3 ∑ j = 1 n − i − 2 ∑ k = 1 n − i − j − 1 1 \sum\limits_{i=1}^{n-3}{\sum\limits_{j=1}^{n-i-2}{\sum\limits_{k=1}^{n-i-j-1}{1}}} i=1∑n−3j=1∑n−i−2k=1∑n−i−j−11
读者可以自行证明,接下来
∑ i = 1 n − 3 ∑ j = 1 n − i − 2 n − i − j − 1 \sum\limits_{i=1}^{n-3}{\sum\limits_{j=1}^{n-i-2}{n-i-j-1}} i=1∑n−3j=1∑n−i−2n−i−j−1
化开
∑ i = 1 n − 3 ( ( n − i ) ( n − i − 2 ) − ∑ j = 1 n − i − 2 j + 1 ) \sum\limits_{i=1}^{n-3}{((n-i)(n-i-2)-\sum\limits_{j=1}^{n-i-2}{j+1})} i=1∑n−3((n−i)(n−i−2)−j=1∑n−i−2j+1)
等差数列公式走起
∑ i = 1 n − 3 ( ( n − i ) ( n − i − 2 ) − ( n + 1 − i ) ( n − i − 2 ) 2 ) \sum\limits_{i=1}^{n-3}{((n-i)(n-i-2)-\frac{(n+1-i)(n-i-2)}{2})} i=1∑n−3((n−i)(n−i−2)−2(n+1−i)(n−i−2))
再化开
∑ i = 1 n − 3 1 2 ( n 2 − 2 i n + 2 i 2 + i − n − 2 ) \sum\limits_{i=1}^{n-3}{\frac{1}{2}(n^2-2in+2i^2+i-n-2)} i=1∑n−321(n2−2in+2i2+i−n−2)
然后套一个 ∑ i = 1 n i 2 = n ( n + 1 ) ( 2 n + 1 ) 6 \sum\limits_{i=1}^{n}{i^2}=\frac{n(n+1)(2n+1)}{6} i=1∑ni2=6n(n+1)(2n+1)公式就可以推出答案。
可见推 f ( k , n ) f(k,n) f(k,n)要用到 ∑ i = 1 n i k − 2 \sum\limits_{i=1}^{n}{i^{k-2}} i=1∑nik−2的公式,而这个公式是没有通项式的所以我们要换个思路。
可以转换一下模型, f ( i , k ) f(i,k) f(i,k)表示在 k k k个球中间 k − 1 k-1 k−1个空放 i i i个隔板把这些球分成不同数量的方案数,这明显是 A i k − 1 A_{i}^{k-1} Aik−1,但会有重复,所以应该是 C i k − 1 C_{i}^{k-1} Cik−1,答案为 ∑ i = 1 n − 1 C i n − 1 \sum\limits_{i=1}^{n-1}{C_{i}^{n-1}} i=1∑n−1Cin−1
在这里如果用杨辉三角爆推有 60 60 60分。但这个式子也没什么用,因为 C i n − 1 C_{i}^{n-1} Cin−1无法处理,除非用杨辉三角或逆元,当模数是质数是可以用卢卡斯定理(但很可惜,这道题模数不是)但 ∑ i = 1 n − 1 C i n − 1 = 2 n − 1 \sum\limits_{i=1}^{n-1}{C_{i}^{n-1}}=2^{n-1} i=1∑n−1Cin−1=2n−1!!想象一下,对于 n − 1 n-1 n−1个空,每个空对应放与不放两种选择,而所有的情况就对应了所有的组合数。
那么有了这个结论,可以用快速幂优化到 80 80 80分(事实证明数据没造好,连普通的乘法都有 80 80 80),接下来怎么优化, n ≤ 5 × 1 0 1 0 7 n\leq5\times10^{10^7} n≤5×10107,似乎要用高精,但空间又不够(毒瘤出题人只给了 4 M 4M 4M空间( 275307894 a 275307894a 275307894a:还不够吗,足足是 s t d std std的 5 5 5倍!!!)),所以考虑一下模数,我们会发现模数为 2 60 − 1 2^{60}-1 260−1,那么 n = 61 n=61 n=61时和 n = 1 n=1 n=1时答案是一样的,所以可以 % 60 \%60 %60之后直接做普通乘法。但 % 60 \%60 %60又是个问题,高精不可能。
有这样两个定理: ( a % m o d ) ( b % m o d ) = a b % m o d (a\%mod)(b\%mod)=ab \% mod (a%mod)(b%mod)=ab%mod和 ( a % m o d + b % m o d ) % m o d = ( a + b ) % m o d (a\%mod+b\%mod)\%mod=(a+b) \% mod (a%mod+b%mod)%mod=(a+b)%mod
回想一下快读的过程,只有 × \times ×和 + + +两种,那么直接可以用快读的方法过掉,最大用时 497 m s 497ms 497ms,( 275307894 a 275307894a 275307894a:你看,时限还是 s t d std std的 2 2 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);
}