1008: QAQ的矩阵价值
时间限制: 1 Sec 内存限制: 128 MB
提交: 21 解决: 7
[提交][状态][讨论版]
题目描述
QAQ有一个这样的矩阵序列(假定我们用二维数组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]∗10n−j
。
QAQ定义一个矩阵的价值为矩阵中所有元素价值之和。
为了增加难度,QAQ将该矩阵序列变成两个不同的矩阵序列:(如n=5时)
一 二
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,ans2
。
注:矩阵的行列下标均是1−n
。
输入
第一行输入一个整数T
,代表有T组测试数据。
每组数据输入一个整数n,代表矩阵序列是n∗n的。
注:1<=T<=10000,1<=n<=100000
。
输出
对每组数据,输出三个整数ans0,ans1,ans2
,中间用空格隔开,最后一个数后面没有空格。
由于结果很大,请对(109+7)
取余。
样例输入
5
1
3
5
100
5000
样例输出
1 1 1
356 331 136
60355 57631 13715
311833527 324678596 120264545
770817050 915988694 926824673
一、考虑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);
时间复杂度O(n)。
AC代码 :
#include<cstdio>
typedef long long LL;
const LL mod = 1e9 + 7;
const LL MM = 100011;
LL ans0[MM],ans1[MM],ans2[MM],one[MM],add[MM];
int main()
{
int T,N,i,a;
LL pl = 1,kl = 1;
ans0[1] = 1; ans2[1] = 1; one[1] = 1,add[1] = 1,ans1[1] = 1;
for(i = 2 ; i <= MM ; i++)
one[i] = (one[i - 1] * 10 + 1 ) % mod;
for(i = 2 ; i <= MM ; i++){
pl = ( pl * 10 % mod + i ) % mod;
kl = (kl + i) % mod;
if(i & 1)
a = (i + 1) / 2;
else
a = i / 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;
}