1008: QAQ的矩陣價值 [思維]
時間限制: 1 Sec 內存限制: 128 MB提交: 43 解決: 14 統計
題目描述
QAQ有一個這樣的矩陣序列(假定我們用二維數組a[][]a[][]來記錄該序列):
n = 1 n = 2 n = 3 n = 4 n = 5 n = ...
1 1 2 1 2 3 1 2 3 4 1 2 3 4 5
1 1 1 2 2 1 2 3 3 1 2 3 4 4
1 1 1 1 2 2 2 1 2 3 3 3 ......
1 1 1 1 1 2 2 2 2
1 1 1 1 1
QAQ定義矩陣元素a[i][j]a[i][j]的價值 = a[i][j]∗10n−ja[i][j]∗10n−j。
QAQ定義一個矩陣的價值爲矩陣中所有元素價值之和。
一 二
1 0 0 0 0 0 0 0 0 5
1 2 0 0 0 0 0 0 4 4
1 2 3 0 0 0 0 3 3 3
1 2 2 2 0 0 2 2 2 2
1 1 1 1 1 1 1 1 1 1
對於上面給出的三個矩陣,請你分別求出它們的價值ans0,ans1,ans2ans0,ans1,ans2。
注:矩陣的行列下標均是1−n1−n。
輸入
每組數據輸入一個整數nn,代表矩陣序列是n∗nn∗n的。
注:1<=T<=10000,1<=n<=1000001<=T<=10000,1<=n<=100000。
輸出
對每組數據,輸出三個整數ans0,ans1,ans2ans0,ans1,ans2,中間用空格隔開,最後一個數後面沒有空格。
由於結果很大,請對(109+7)(109+7)取餘。
樣例輸入
5
1
3
5
100
5000
樣例輸出
1 1 1
356 331 136
60355 57631 13715
311833527 324678596 120264545
770817050 915988694 926824673
來源
AC代碼:
一、考慮n階初始矩陣的價值ans[n]
發現n階比n−1階每次多出外圍的一圈
1 2 3 4 … n
.
.
4
3
2
1
ans[n]=ans[n−1]∗10+(1+2+…+n)+(1234…n)−n;
(1234…n)可以先預處理一下,這樣可以很快速求出初始矩陣的價值。
二、考慮n階①矩陣的價值ans1[n]
我們統計一下每列的和,因爲每列元素乘10的冪次數是一樣的。
(1)若n爲奇數,第n階比n−1階每列多出
123…(n/2−1)(n/2+1)(n/2−1)…321
(2)若n爲偶數,第n階比n−1階每列多出
123…(n/2−1)(n/2)(n/2)(n/2−1)…321
當然這也是有規律的
如12321 和123321,有123321=12321∗10+111
如1221和12321,有12321=1221∗10+111
用one[n]表示n個1連起來的值即11111….1共n個。
用add[n]表示第n階比第n−1階多出的值
那麼有
one[n]=one[n−1]∗10+1;
add[n]=add[n−1]∗10+one[n& 1?n/2+1:n/2];
ans1[n]=ans1[n−1]+add[n];
三、考慮n階②矩陣的價值ans2[n]
發現n階比n−1階每次多出第n列的元素即
n
..
3
2
1
這樣直接有ans2[n]=ans2[n−1]∗10+(1+2+3+…+n);
#include<cstdio>
typedef long long LL;
const LL mod=1e9+7;
const LL M=100011;
LL ans0[M],ans1[M],ans2[M],one[M],add[M];
int main()
{
int T,N,i,a;
LL pl=1,kl=1;
ans0[1]=ans1[1]=ans2[1]=one[1]=add[1]=1;
for(i=2;i<=M;i++)
{
one[i]=(one[i-1]*10+1)%mod;
}
for(i=2;i<=M;i++)
{
pl=(pl*10%mod+i)%mod;
kl=(kl+i)%mod;
a=(i+1)/2;
add[i]=(add[i-1]*10%mod+one[a])%mod;
ans0[i]=(ans0[i-1]*10%mod+pl-i+kl)%mod;
ans1[i]=(ans1[i-1]*10%mod+add[i])%mod;
ans2[i]=(ans2[i-1]*10%mod+kl)%mod;
}
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
printf("%lld %lld %lld\n",ans0[N],ans1[N],ans2[N]);
}
return 0;
}