1. 程式人生 > >落谷P3941 入陣曲

落谷P3941 入陣曲

clu max png class 方便 += 規模 測試數據 有一個

題目背景

pdf題面和大樣例鏈接:http://pan.baidu.com/s/1cawM7c 密碼:xgxv

丹青千秋釀,一醉解愁腸。 
無悔少年枉,只願壯誌狂。 

題目描述

小 F 很喜歡數學,但是到了高中以後數學總是考不好。

有一天,他在數學課上發起了呆;他想起了過去的一年。一年前,當他初識算法競賽的 時候,覺得整個世界都煥然一新。這世界上怎麽會有這麽多奇妙的東西?曾經自己覺得難以 解決的問題,被一個又一個算法輕松解決。

小 F 當時暗自覺得,與自己的幼稚相比起來,還有好多要學習的呢。

一年過去了,想想都還有點恍惚。

他至今還能記得,某天晚上聽著入陣曲,激動地睡不著覺,寫題寫到雞鳴時分都興奮不 已。也許,這就是熱血吧。

技術分享

也就是在那個時候,小 F 學會了矩陣乘法。讓兩個矩陣乘幾次就能算出斐波那契數列的 第 10^{100}10100 項,真是奇妙無比呢。

不過,小 F 現在可不想手算矩陣乘法——他覺得好麻煩。取而代之的,是一個簡單的小 問題。他寫寫畫畫,畫出了一個 n \times mn×m 的矩陣,每個格子裏都有一個不超過 kk 的正整數。

小 F 想問問你,這個矩陣裏有多少個不同的子矩形中的數字之和是 kk 的倍數? 如果把一個子矩形用它的左上角和右下角描述為 (x_1,y_1,x_2,y_2)(x1?,y1?,x2?,y2?),其中x_1 \le x_2,y_1 \le y_2x1?x2?,y1?y2?; 那麽,我們認為兩個子矩形是不同的,當且僅當他們以 (x_1,y_1,x_2,y_2)(x1?,y1?,x2?,y2?) 表示時不同;也就是 說,只要兩個矩形以 (x_1,y_1,x_2,y_2)(x1?,y1?,x2?,y2?) 表示時相同,就認為這兩個矩形是同一個矩形,你應該 在你的答案裏只算一次。

輸入輸出格式

輸入格式:

從標準輸入中讀入數據。

輸入第一行,包含三個正整數 n,m,kn,m,k。

輸入接下來 nn 行,每行包含 mm 個正整數,第 ii 行第 jj 列表示矩陣中第 ii 行第 jj 列 中所填的正整數 a_{i,j}ai,j?

輸出格式:

輸出到標準輸出中。

輸入一行一個非負整數,表示你的答案。

輸入輸出樣例

輸入樣例#1: 復制
2 3 2 
1 2 1 
2 1 2
輸出樣例#1: 復制
6 

說明

【樣例 1 說明】

這些矩形是符合要求的: (1, 1, 1, 3),(1, 1, 2, 2),(1, 2, 1, 2),(1, 2, 2, 3),(2, 1, 2, 1),(2, 3, 2, 3)。

子任務會給出部分測試數據的特點。如果你在解決題目中遇到了困難,可以嘗試只解 決一部分測試數據。

每個測試點的數據規模及特點如下表:

技術分享

特殊性質:保證所有 a_{i,j}ai,j? 均相同。

題解:

  這個題目我們先考慮套路一下,記一下每一列的前綴合,然後枚舉兩行,把兩行之間的數字壓縮成一個數,這樣就變成了一個序列問題,對答案有貢獻的區間只有滿足(sum[r]-sum[l-1])%k==0,即sum[r]%k==sum[l-1]%k,所以我們開一個sum的桶,每次查詢和sum[r]%k相同的右端點個數就可以了。

題外話:

  很久沒有發博客了,因為都在做學校內部的題目,不方便發出來,真是,自己回來看博客的時候,發現雖然自己沒動,但很多東西都變了。

代碼:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#define RG register
#define ll long long
#define MAXN 410
using namespace std;
ll sum[MAXN][MAXN],a[MAXN][MAXN],tong[1000100],sum2[MAXN],ans;
int n,m,k;

inline void work(int l,int r){
  for(RG int i=1;i<=m;i++){
    ll now=sum[i][r]-sum[i][l-1];
    sum2[i]=(sum2[i-1]+now)%k;
    tong[sum2[i-1]]++;
    ans+=tong[sum2[i]];
  }
  for(RG int i=0;i<=m-1;i++){
    tong[sum2[i]]--;
    sum2[i]=0;
  }
}

int main()
{
  scanf("%d%d%d",&n,&m,&k);
  for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++) scanf("%lld",&a[i][j]);
  }
  for(RG int j=1;j<=m;j++){
    for(RG int i=1;i<=n;i++){
      sum[j][i]=sum[j][i-1]+a[i][j];
    }
  }
  for(RG int l=1;l<=n;l++){
    for(RG int r=l;r<=n;r++){
      work(l,r);
    }
  }
  printf("%lld",ans);
  return 0;
}

落谷P3941 入陣曲