3.5~3.6联考题解

本来想加个密码的,后来一想全HE就咱们这几个人,外省的dalao愿看也没事儿,就公开算了,省得加密码各种麻烦。

先补这两天的题解吧……如果有空的话我可能会把上次联考的题解补上= =(中午没睡觉,现在困得很,根本没法写题……

算算算number

感觉出题人出题的时候zz了吧,费了半天搞出来一个极其麻烦还跑得慢的做法是要闹哪样啊……

算了,写一写$O(nk)$做法的推导过程吧,虽然其实非常好推……

首先定义$S_i$表示到$1~i$位置的前缀和,并且规定$S_0=0$,那么

\begin{align}Ans_i=&\sum_{j=0}^{i-1}\left(S_i-S_j\right)^k\\=&\sum_{j=0}^{i-1}\sum_{x=0}^k C_k^xS_i^x\left(-S_j\right)^{k-x}\left(二项式定理\right)\\=&\sum_{x=0}^k C_k^x S_i^x\sum_{j=0}^{i-1}\left(-S_j\right)^{k-x}\end{align}

然后就很好搞了,首先枚举$x$,然后维护$\left(-S_j\right)^{k-x}$的前缀和即可。组合数是可以直接一边算一边递推的,不需要再预处理了。

直接算是$O(nk\log k)$的,加上一些线性预处理逆元之类的技巧就可以降到$O(nk+n\log p)$了,实测极限数据只需要不到1.3s就可以出解,并且不需要利用数据随机这个性质。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=50010,p=1000000007;
 6 int qpow(int,int);
 7 int fac[maxn],fac_inv[maxn],inv[maxn];
 8 int T,n,k,s[maxn],s_k[maxn],s_inv[maxn],t[maxn],a[maxn],ans[maxn];
 9 int main(){
10     fac[0]=fac_inv[0]=1;
11     for(int i=1;i<=50001;i++)fac[i]=(long long)fac[i-1]*i%p;
12     fac_inv[50001]=qpow(fac[50001],p-2);
13     for(int i=50001-1;i;i--)fac_inv[i]=(long long)fac_inv[i+1]*(i+1)%p;
14     for(int i=1;i<=50001;i++)inv[i]=(long long)fac[i-1]*fac_inv[i]%p;
15     scanf("%d",&T);
16     while(T--){
17         memset(s,0,sizeof(s));
18         memset(ans,0,sizeof(ans));
19         scanf("%d%d",&n,&k);
20         for(int i=1;i<=n;i++){
21             scanf("%1d",&s[i]);
22             s[i]+=s[i-1];
23             s_k[i]=qpow(s[i],k);
24             s_inv[i]=qpow(s[i],p-2);
25         }
26         fill(t,t+n+1,1);
27         for(int x=0,C=1;x<=k;x++){
28             copy(t,t+n+1,a);
29             for(int i=1;i<=n;i++){
30                 a[i]=(a[i]+a[i-1])%p;
31                 ans[i]=(ans[i]+(long long)C*s_k[i]%p*a[i-1]%p)%p;
32             }
33             for(int i=0;i<=n;i++){
34                 t[i]=(long long)t[i]*((p-s[i])%p)%p;
35                 s_k[i]=(long long)s_k[i]*s_inv[i]%p;
36             }
37             C=(long long)C*(k-x)%p*inv[x+1]%p;
38         }
39         for(int i=1;i<=n;i++)printf("%d ",ans[i]);
40         printf("\n");
41     }
42     return 0;
43 }
44 int qpow(int a,int b){
45     int ans=1;
46     for(;b;b>>=1,a=(long long)a*a%p)if(b&1)ans=(long long)ans*a%p;
47     return ans;
48 }
49 /*
50 2
51 10 2
52 3672415495
53 10 2
54 9040607879
55 Answer:
56 9 117 474 634 1066 1200 2075 3043 6238 8668
57 81 81 201 201 633 633 1690 3802 6539 11435
58 */

所以你们看,这题就是个基本的二项式定理,换句话说就是比较水的高考题……

买买买buy

T(o)B(e)C(ompleted)……

树树树mst

还没有去学Boruvka算法……TBC……

Day2的三道题期待中……

时间: 2024-08-25 14:14:45

3.5~3.6联考题解的相关文章

8.9联考题解

今天的题有质量多了,尤其是第一题不再毫无意义,果然考这样的试比较有收获. 时间限制:1sec  内存限制:128MB 题解       刚开始看的时候没有思路.不过这样的考试才叫正常嘛,前两天T1那是什么玩意= =.边读题边写前缀和.离散之类的词,但是前缀和并不能处理出题目中所要求的情况,3*10^5大概最多nlogn.举了几个例子,发现好像和后面大于它的数有关,想了想怎么求它后面大于它的数字个数,过了一会猛然发现我举的例子也太特殊了,全都是单调递增的,有点挫败,就去做后面的题了.T2做了很久还

8.8联考题解

今天的T1让我怀疑我是不是在做奥赛题--这考的是什么知识点啊这个,会不会用绝对值函数? Evensgn 的债务 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Evensgn 有一群好朋友,他们经常互相借钱.假如说有三个好朋友A,B,C.A 欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.Evensgn 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠C20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了 

8.13联考题解

最长上升子串 时间限制: 2 Sec  内存限制: 64 MB 样例输入 67 2 3 1 5 6 样例输出 5 题解       刚一读题觉得和昨天T3相似度极高,只不过是久违的子串.还是想动归思路,f[i][1/0]表示到第i位是/否已经改变过序列的值,然后大概就是个择优转移的思路:受到昨天那题局限用一个辅助数组记录了一下改变后的值,贪心策略把它设为a[i-1][0]+1,.开始上手打,代码倒是很短,怎么想怎么觉得不对劲,自己凭着感觉开始刻意造数据卡这个做法.试了几组数之后成功用123745

8.10联考题解

早上起来莫名困,天天晚上十点睡为什么会困我也不是很懂--然后就迷迷瞪瞪做题,一直都不大清醒.因为一点智障的知识漏洞T3完全挂,然后T2炸内存T1做了两个多小时没做出来~但是也只能说明自己弱,好在现在发现这些坑总比联赛之后发现好得多吧. Evensgn 剪树枝 出题人:Vincent 时间限制:1s 空间限制:128MB 题目描述 繁华中学有一棵苹果树.苹果树有 n 个节点(也就是苹果),n ? 1 条边(也就是树枝).调皮的 Evensgn 爬到苹果树上.他发现这棵苹果树上的苹果有两种:一种是黑

8.12联考题解

所谓今天的题格外水,dalao们纷纷AK--但是本蒟蒻并没有看出来有多水啊--虽然还是水过了一道题,然后剩下的题就照常地转不过来弯,分数和往常并没有多大变化= =. 灌水 时间限制:1s 空间限制:256MB 样例输入1: 3 1 样例输出1: 3 1 2 样例输入2: 4 1 样例输出2: 4 3 1 2 样例输入3: 8 17 样例输出3: 6 2 3 1 8 4 5 7 题解       这个题,第一眼看过去很interesting,第二眼看过去一脸茫然--头一遍读题的时候看到数据范围里那

8.7联考题解

前两题很水啊--没必要开三篇了就扔到一篇里去了.改水题异常艰难,代码量很小然而我又被什么奇怪的东西绊住了. Passward 时间限制: 1 Sec  内存限制: 512 MB 题目描述 你来到了一个庙前,庙牌上有一个仅包含小写字母的字符串 s. 传说打开庙门的密码是这个字符串的一个子串 t,并且 t 既是 s 的前缀又是 s 的后缀并且还在 s 的中间位置出现过一次. 如果存在这样的串,请你输出这个串,如有多个满足条件的串,输出最长的那一个. 如果不存在这样的串,输出"Just a legen

8.11联考题解

样例输入: 3 6 0 -1 1 1 0 -1 -1 1 0 1 2 3 1 2 3 样例输出: 3 题解      不要看上面那个吓人的时间限制--实际上内网给了4Sec,高明的模拟能过:外网给的时间比这还多,直接暴力模拟就能A,这就是为什么我今天成绩莫名高了不少.刚开始就只想到了模拟,用链表可以稍微优化一点有限,然而时间效率近似于n*答案,要依靠答案的大小来决定时间效率,让我不由得想到某名为<天鹅会面>的惨痛事故.想了很久还是没想出来,直接把模拟当做骗分程序来写,连快读都没有写:自认为是今

2015.10.16赛码联考题解,非正确,求大神指导。

//只AC了20%.说的就是11个位置一字型排开0-10.扔硬币到这些位置,然后有个帽子可以每次移动最多一个位置,初始位置5. //思考:相当于遍历一个3叉树. #include <iostream>#include <vector>#include <cmath>using namespace std; struct coins{ int x; int T;};int main (){ int n,i,j,k; coins coins1[100000]={0}; in

10.29 FJ四校联考

//四校联考Rank 16 感觉很滋磁 (虽然考的时候抱怨厦门一中出的数学题很NOIP///) 圈地 [问题描述] n根长度不一定相同的木棍,至多可以对其中一根切一刀,然后用其中的任意根围一个三角形,求三角形的最大面积.设面积为S,输出16*S^2对998244353取模后的答案.特别地,无解输出-1. 注:退化的三角形(面积为零)不被认为是三角形,答案应该为-1. [输入文件] 输入文件为tri.in. 输入文件第一行包含两个正整数n和998244353. 第二行包含n个正整数,表示每根木棍的