【HPU 1008 QAQ的矩阵价值】

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值