2020 CCPC

地址:http://acm.hdu.edu.cn/showproblem.php?pid=6898

 队友A掉的题。赛后看了下,觉得有必要好好写一个题解。

题意:

给出A,K',求C

而C需要K,所以需要通过K'求K

解析:

1:暴力做法

由题中公式,先求K,然后直接四层for求出C来,打印即可。

#include <bits/stdc++.h>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e3+10;
vector<int>g[maxn];
int main(){
    int t;
    cin>>t;
    while(t--)
    {
        int mp[55][55],k[4][4];
        int c[55][55];
        memset(c,0,sizeof(c));
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                cin>>mp[i][j];
        int sum=0;
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
                {
                    cin>>k[i][j];
                    sum+=k[i][j];
                }
        for(int i=1;i<=3;i++)
        {
            for(int j=1;j<=3;j++)
            {
                k[i][j]=k[i][j]/(sum*1.0);
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                for(int o=1;o<=min(n-i+1,3);o++)
                {
                    for(int p=1;p<=min(n-j+1,3);p++)
                    {
                        c[i][j]+=mp[i+o-1][j+p-1]*k[o][p];                        
                    }
                }    
                            
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(j<n)
                    cout<<(int)c[i][j]<<" ";
                else
                    cout<<(int)c[i][j]<<endl;
            }
        //    cout<<endl;
        }
    }
}

2:思维做法

这里就得详细得写一下了。

首先对于C的公式:

画一下,就可以发现,对于Ci,j,在A中就是以Ai,j为左上角到右下角的范围,其同样大小的范围放在K中,K中一定是以K1,1做为左上角。对应位置两两相乘,再相加即可。

举个对应关系:

然后再看这个无穷:

首先求C^1,然后C^1变成了新的A,也就是每次算出的矩阵C,都要在下一步做为A与K进行运算。

拿样例2举例:

(1)发现,无穷次乘,C1,1就要无限乘1/2,它只会越乘越小,最后趋于0,其他元素也是如此。

所以对于K'中如果出现多个数字,那么K中一定会出现小数(sum==1,其一定小于1),一个数无限乘一个小于1的小数,最后一定趋向于0。

所以如果K'出现了多个数,结果一定全0.

(2)如果K'只出现了一个数,那么这个数一定为1。重要的是它的位置。

观察C的计算公式,发现K1,1是必然要算的,所以如果1在K1,1位置,那么无穷次,C必然不变。

如果1在其他位置,最后一定会趋向于0的,这个随便举个例子就可以说明的。

所以总的结论就是:

i=1,j=1之外出现了非0数,输出全0,否则输出原C。

#include <bits/stdc++.h>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e3+10;
vector<int>g[maxn];
int a[maxn];
int b[maxn];
int vis[maxn];
int ok  = 0 ;
int x,y;
int mp[maxn][maxn],k[4][4];
int main(){
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        int  ok=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                cin>>mp[i][j];
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
                {
                    cin>>k[i][j];
                    if(i!=1&&j!=1&&k[i][j]!=0)
                    {
                        ok=1;
                    }
                }
        if(ok)
        {
            
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    if(j<n)
                        cout<<"0"<<" ";
                    else
                        cout<<"0"<<endl;
                }
                //    cout<<endl;
            }        
        }else
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                    {
                    if(j<n)
                        cout<<mp[i][j]<<" ";
                    else
                        cout<<mp[i][j]<<endl;
                    }
            }  
        }
    }
}
原文地址:https://www.cnblogs.com/liyexin/p/13718925.html