HDU 5084 HeHe (找规律)

HeHe

Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 311    Accepted Submission(s): 116


Problem Description










You are expected to write a program to point out some elements of  MM .
 

Input
Multi test cases (about 100), every case occupies two lines.
The first line contains an integer n.
Then second line contain 2*n-1 integers  t0,t1,t2,t3,,t2n4,t2n3,t2n2  separated by exact one space.
The third line contains an integer m, indicates the number of query.
Next m lines will give queries
r0r1r2rm1c0c1c2cm1
For  r0,c0  the program will query the element of  MM  which locates in the  rth0  row,  cth0  column. For  ri,ci(0<i<m) , assume that the answer of  i1th  query is ANS, the program will query the element of  MM  which locates in  ((ri+ANS)%n)th  row,  ((ci+ANS)%n)th  column.
Please process to the end of file.
[Technical Specification]
1n1000
0ti100
0ri,cin1
1m100000
 

Output
For each case,output the sum of the answer of each query.
 

Sample Input
  
  
3 1 2 3 1 2 2 0 0 1 2 4 10 5 7 2 10 5 7 3 1 2 3 0 2 1 2 1 2 3 4 0 0 0 1 1 0 1 1
 

Sample Output
  
  
23 348 22
Hint
 

Source
 

题目大意:给出一个矩阵M里元素的值t[0],t[1],t[2],……,t[n-1],t[n],t[n+1],……,t[2*n-1],t[2*n-2]。
求出 S=M*M,给出m对r[i],c[i],
当i = 0时,得到S[ r[0] ][ c[0] ];
当i = 1时,ans=S[ r[0] ][ c[0] ],得到S[ (r[1]+ans)%n ][ (c[1]+ans)%n ];
当i = 2时,ans=S[ (r[1]+ans)%n ][ (c[1]+ans)%n ],得到S[ (r[2]+ans)%n ][ (c[2]+ans)%n ];

……………………………………………………………………

当 i = m-1时,ans=S[ (r[m-2]+ans)%n ][ (c[m-2]+ans)%n ],得到S[ (r[m-1]+ans)%n ][ (c[m-1]+ans)%n ]。
求S[ r[0] ][ c[0] ]+S[ (r[1]+ans)%n ][ (c[1]+ans)%n ]+……+S[ (r[m-2]+ans)%n ][ (c[m-2]+ans)%n ]+S[ (r[m-1]+ans)%n ][ (c[m-1]+ans)%n ]。

解题思路:
1、矩阵S=M*M的所有元素值都求出后,做m次操作。

对于矩阵M,我们假设行列的下标均是从0开始的,则行列的下标均是由n-1结束的,如果对矩阵M和矩阵S,都以矩阵M中 元素的下标为下标,如上图中红黄线所画,每一个t都有一个下标,即以该下标为矩阵M和矩阵S的下标。那么对于矩阵M,有M[n-1][n-1]=t[n-1],M[0][2*n-2]=t[n-1],……
对于矩阵S=M*M,我们有
S[0][2*n-2]=t[0]*t[2*n-2]   +t[1]*t[2*n-3]+t[2]*t[2*n-4]+……+t[n-2]*t[n]+t[n-1]*t[n-1]
S[1][2*n-3]=                         t[1]*t[2*n-3]+t[2]*t[2*n-4]+……+t[n-2]*t[n]+t[n-1]*t[n-1] + t[n]*t[n-2]
S[2][2*n-4]=                                               t[2]*t[2*n-4]+……+t[n-2]*t[n]+t[n-1]*t[n-1] + t[n]*t[n-2]   + t[n+1]*t[n-3]
………………………………………………………………
S[n-1][n-1]=
根据上面的式子,知道S[0][2*n-2],就可以快速求出S[1][2*n-3];知道S[1][2*n-3],就可以快速求出S[2][2*n-4]……因此知道矩阵S的一个元素值,可以快速求出矩阵S的n个元素值。

代码如下:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#include <limits.h>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-6)
#define inf (1<<28)
#define sqr(x) (x) * (x)
#define mod 1000000007
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
#define MAX 1005
//
ll t[2*MAX],S[2*MAX][2*MAX];
//标记矩阵S[i][j]的值是否已经求出
bool vis[2*MAX][2*MAX];

int main()
{
    int i,j,n,m,r,c;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0;i<=2*n-2;i++)
            scanf("%I64d",&t[i]);

        memset(vis,false,sizeof(vis));
        //计算矩阵S=M*M中元素的值
        for(i=0;i<=n-1;i++)
        {
            for(j=2*n-2;j>=n-1;j--)
            {
                //已经计算过的不必重复计算
                if(vis[i][j])
                    continue;

                ll ans=0;
                int k1=i,k2=j,k3=n;
                //计算第一个元素的值
                while(k3--)
                    ans+=t[k1++]*t[k2--];
                S[i][j]=ans;
                vis[i][j]=true;//标记

                k1=i+1;
                k2=j-1;
                //计算剩余的n-1个
                while(k1<=n-1&&k2>=n-1)
                {
                    ans=ans-t[k1-1]*t[k2+1]+t[k1+n-1]*t[k2-n+1];
                    S[k1][k2]=ans;
                    vis[k1][k2]=true;//标记
                    k1++;
                    k2--;
                }
            }
        }
        scanf("%d",&m);
        ll sum=0,ans=0;
        //矩阵S的m个位置元素的和
        while(m--)
        {
            scanf("%d%d",&r,&c);
            ans=S[(n-1)-(r+ans)%n][(n-1)+(c+ans)%n];
            sum+=ans;
        }
        printf("%I64d\n",sum);
    }
    return 0;
}



2、矩阵S=M*M的所有元素值不一定全求出来,只是求用得到的值。
如果S=M*M,那么S[x][y]=(矩阵M的第n-1-x行的元素值)*(矩阵M的第n-1+y列的元素值)。
列式表示为:
S[x][y]=t[(n-1-x)]*t[(n-1+y)]+t[(n-1-x)+1]*t[(n-1+y)-1]+……+t[(n-1-x)+(n-2)][(n-1+y)-(n-2)]+t[2*n-2-x][y]

代码如下:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#include <limits.h>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-6)
#define inf (1<<28)
#define sqr(x) (x) * (x)
#define mod 1000000007
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
#define MAX 1005
int n,m,t[2*MAX];
int ans(int x,int y)
{
    int s=0,i,j,k;
    i=n-1-x;
    j=n-1+y;
    for(k=0;k<n;k++)
    {
        s+=t[i]*t[j];
        i++;
        j--;
    }
    return s;
}
int main()
{
    int i,r,c;
    while(~scanf("%d",&n))
    {
        for(i=0;i<=2*n-2;i++)
            scanf("%d",&t[i]);
        ll cnt=0,s=0;
        scanf("%d",&m);
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&r,&c);
            s=ans((r+s)%n,(c+s)%n);
            cnt+=s;
        }
        printf("%I64d\n",cnt);
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值