zoukankan      html  css  js  c++  java
  • 入阵曲:桶,前缀和

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

    谁不会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
    ",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
    ",ans);
    14 }
    然而也只有14行
  • 相关阅读:
    链接和作用域2 C++快速入门43
    位运算符
    代码编辑器和代码浏览器
    关系运算符
    delphi教程 | 第一个程序
    代码编辑器和代码浏览器
    链接和作用域2 C++快速入门43
    delphi教程 | 第一个程序
    位运算符
    [原创 js] 点击即可修改内容函数
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11335210.html
Copyright © 2011-2022 走看看