ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

入阵曲:桶,前缀和

2019-08-11 15:57:20  阅读:206  来源: 互联网

标签:前缀 int sum d% 405 ans buc 入阵曲


给出的题解不错,所以不写得太详细了。

谁不会60分的那真是没办法了。

1 #include<cstdio>
2 int x[405][405],n,m,k,ans;
3 int main(){
4     scanf("%d%d%d",&n,&m,&k);
5     for(int i=1;i<=n;++i)for(int j=1,y;j<=m;++j)scanf("%d",&y),x[i][j]=(x[i-1][j]+x[i][j-1]-x[i-1][j-1]+y)%k;
6     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)for(int p=0;p<i;++p)for(int q=0;q<j;++q)if((x[i][j]-x[p][j]-x[i][q]+x[p][q])%k==0)ans++;
7     printf("%d\n",ans);
8 }
考场上秒写的8行60分暴力

看数据范围,有不少测试点m=2。这有什么用?(肯定和同样矩阵大小而mn均匀的点不一样啦)

永远不要忽视测试点的提示作用。NOIP数据范围就很全。

对于只有两行的矩阵,首先我们只选出单独一行的2种,处理它。

接下来就只有两行一起选的问题了。

扩展到更多行,我们可以发现所有行上的选法是m2的。

而如果把每一行的同一列上的数加起来得到新的一行,这就变成了单行上的问题了。

现在我们只需要O(n)求出单行。

刚开始我感觉不可做。但是实际上,这一行的前i位前缀和为sum[i],那么区间l~r能被k整除当且仅当(sum[r]-sum[l-1])%k==0

证明很简单。因为这一段能整除的话,在加上其它的一段值就是后者的值。

所以我们要找满足条件的l-1。也就是给出sum[r]问有多少sum[l-1]满足条件。

开一堆桶buc,buc[p]表示sum[i]%k==p对应的i的个数。每次以r为区间右端点累加答案时直接加上buc[sum[r]]即可。

而且如果一个sum值本身就是k的倍数,那么也要ans++。

 1 #include<cstdio>
 2 int x[405][405],n,m,mod,buc[1000005],l[405];long long ans;
 3 int main(){
 4     scanf("%d%d%d",&n,&m,&mod);
 5     for(int i=1;i<=n;++i)for(int j=1,y;j<=m;++j)scanf("%d",&x[i][j]),(x[i][j]+=x[i][j-1])%=mod;
 6     for(int i=1;i<=n;++i){
 7         for(int j=1;j<=m;++j)l[j]=0;
 8         for(int j=i;j<=n;++j){
 9             for(int k=1;k<=m;++k)(l[k]+=x[j][k])%=mod,ans+=buc[l[k]]+(l[k]?0:1),buc[l[k]]++;
10             for(int k=1;k<=m;++k)buc[l[k]]--;
11         }
12     }
13     printf("%lld\n",ans);
14 }
然而也只有14行

 

标签:前缀,int,sum,d%,405,ans,buc,入阵曲
来源: https://www.cnblogs.com/hzoi-DeepinC/p/11335210.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有