number number number (规律题+dp打表+高斯消元+矩阵快速幂)

传送门

先dp打表


#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

LL s[50];
int dp[10][20000];

int main()
{
    s[0]=0;
    s[1]=1;
    for(int i=2;i<=15;i++){
        s[i]=s[i-1]+s[i-2];
    }
//    for(int i=0;i<10;i++){
//        cout<<s[i]<<" ";
//    }
//    cout<<endl;
    dp[0][0]=1;
    for(int num=1;num<=10;num++){
        for(int val=1000;val>=0;val--){
            for(int k=0;k<=15;k++){
                dp[num][val+s[k]]|=dp[num-1][val];
//                if(dp[num][val+s[k]]){
//                    cout<<val+s[k]<<endl;
//                }
            }
        }
    }
    for(int i=1;i<=10;i++){
    	for(int j=0;j<=1500;j++){
    		if(!dp[i][j]){
    			cout<<i<<" "<<j<<endl;
    			break;
			}
		}
	}
    return 0;
}

再使用高斯消元+完全主元素+若尔当方法


//高斯消元+完全主元素+若尔当方法
#include<bits/stdc++.h>

using namespace std;

int n;
double a[10][10];//对应的增广矩阵
double ans[10];//对应的答案
//交换行
void swap_r(int q,int p)
{
    for(int i=1;i<=n+1;i++){
        double t=a[p][i];
        a[p][i]=a[q][i];
        a[q][i]=t;
    }
}
//交换列
void swap_c(int q,int p)
{
    for(int i=1;i<=n+1;i++){
        double t=a[i][p];
        a[i][p]=a[i][q];
        a[i][q]=t;
    }
}

void prt()
{
    for(int i=1;i<=n+1;i++){
        for(int j=1;j<=n+1;j++){
            printf("%2.5f ",a[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

void gs()
{
    for(int i=1;i<n;i++){
        //找出i i位置对应最大的主元素
        double m=fabs(a[i][i]);
        int p=i,q=i;
        for(int j=i+1;j<=n;j++){
            for(int k=i;k<=n;k++){
                if(fabs(a[j][k])>m){
                    m=fabs(a[j][k]);
                    p=j;
                    q=k;
                }
            }
        }
        if(p!=i){
            swap_r(p,i);
            printf("交换%d与%d行\n",p,i);
        }
        if(q!=i){
            swap_c(q,i);
            printf("交换%d与%d列\n",q,i);
        }
        prt();
        //把i i位置下面的进行消元
        printf("进行消元\n");
        for(int j=i+1;j<=n;j++){
            if(a[i][j]==0.0){
                continue;
            }
            double t=a[j][i]/a[i][i];
            a[j][i]=0.0;
            for(int k=i+1;k<=n+1;k++){
                a[j][k]-=t*a[i][k];
            }
        }
        prt();
    }
}//此时已经换为了一个上三角形
//进行行标准型的变换
void red()
{
    for(int i=n;i>1;i--){
        printf("%d %d位置上方进行消元\n",i,i);
        for(int j=i-1;j>=1;j--){
            if(a[j][i]==0){
                continue;
            }
            double t=a[j][i]/a[i][i];
            a[j][i]=0.0;
            //因为i左列的不必处理,因为i这行左边都为0
            for(int k=i+1;k<=n+1;k++){
                a[j][k]-=t*a[i][k];
            }
        }
        prt();
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n+1;j++){
            scanf("%lf",&a[i][j]);
        }
    }
    //在下面增加一行1 2 3 4 0,此处在后面消元中作用大
    //这个下面加了这一行最后 答案进行处理,使得矩阵既可以进行行变换也可以进行列变换
    for(int i=1;i<=n;i++){
        a[n+1][i]=i;
    }
    for(int i=1;i<=n+1;i++){
        for(int j=1;j<=n+1;j++){
            printf("%f ",a[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    gs();
    red();
    for(int i=1;i<=n;i++){
        ans[(int)a[n+1][i]]=a[i][n+1]/a[i][i];
    }
    for(int i=1;i<=n;i++){
        printf("x%d = %f\n",i,ans[i]);
    }
    return 0;
}

最后再使用矩阵快速幂


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll MOD=998244353;
const int N=4;

struct node
{
	ll a[10][10];
};

node shu,ans,mp;
//shu是输入的矩阵,ans是所求答案
node matrix(node x,node y)
{
    for(int i=1;i<=N;i++)
        for(int j=1;j<=N;j++){
            mp.a[i][j]=0;
            for(int p=1;p<=N;p++)
                mp.a[i][j]=(mp.a[i][j]+x.a[i][p]*y.a[p][j]+MOD)%MOD;
            //矩阵乘法
        }
    return mp;
}
void work(ll k)
{
    //矩阵快速幂
	for(int i=1;i<=N;i++)
			for(int j=1;j<=N;j++)
				ans.a[i][j]=0;
	for(int i=1;i<=N;i++) ans.a[i][i]=1;
	node t=shu;
    while(k){
        if(k&1)
            ans=matrix(ans,t);
        k>>=1;
        t=matrix(t,t);
    }
}

int main()
{
	ll n;
	for(int i=1;i<=N;i++){
        for(int j=1;j<=N;j++){
            shu.a[i][j]=0;
		}
	}
	shu.a[1][1]=4;
	shu.a[1][2]=-4;
	shu.a[1][3]=1;
	shu.a[2][1]=1;
	shu.a[3][2]=1;
	while(cin>>n)
	{

		if(n==1) printf("4\n");
		else if(n==2) printf("12\n");
		else if(n==3) printf("33\n");
		else
		{
			work(n-3);
			printf("%lld\n",(ans.a[1][1]*33%MOD+ans.a[1][2]*12%MOD+ans.a[1][3]*4%MOD)%MOD);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/81072938
今日推荐