列表

详情


NC206072. 拆分

描述

牛牛准备送给牛妹一条项链,但是项链太长了,于是他准备将项链拆掉。
牛妹有一些不喜欢的数,所以拆分出来的长度中一定要有至少一个不是牛妹不喜欢的(不然就送不出去了)。
注意,由于项链上的每一颗珠子都不同,所以1 5 1和1 1 5是两种不同的拆分方案,不拆也是一种方案。

输入描述

第一行:两个数N和P。

第二行:一个数K,表示牛妹有K个不喜欢的数。

第三行:K个牛妹不喜欢的数T。

输出描述

一个整数表示拆分方案对P取模后的值,不保证P是质数。

示例1

输入:

5 10007
2
2 3

输出:

14

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1064ms, 内存消耗: 632K, 提交时间: 2020-09-05 18:12:24

#include<bits/stdc++.h>
using namespace std;
//dengyaotriangle!

const int maxn=105;

int mdn;
struct mat{
    int v[maxn][maxn];
    mat(){memset(v,0,sizeof(v));}
};

mat operator*(const mat&a,const mat&b){
    mat c;
    for(int i=0;i<maxn;i++){
        for(int k=0;k<maxn;k++){
            for(int j=0;j<maxn;j++){
                c.v[i][j]=(c.v[i][j]+a.v[i][k]*(long long)b.v[k][j])%mdn;
            }
        }
    }
    return c;
}

template<typename t,typename te,typename tm> inline t qpowm(t bse,te ex,tm mdn){t ans=(mdn!=1);while(ex){if(ex&1)ans=(ans*bse)%mdn;bse=(bse*bse)%mdn;ex>>=1;}return ans;}

int main(){
    long long n;
    cin>>n>>mdn;
    mat bse;
    int k;
    cin>>k;
    for(int i=1;i<maxn;i++)bse.v[i-1][i]=1;
    while(k--){
        int u;cin>>u;
        bse.v[u-1][0]=1;
    }
    mat e;
    int t=qpowm<long long>(2,n-1,mdn);
    for(int i=0;i<maxn;i++)e.v[i][i]=1;
    while(n){
        if(n&1)e=e*bse;
        n>>=1;bse=bse*bse;
    }
    int a=e.v[0][0];
    cout<<(t-a+mdn)%mdn;
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 810ms, 内存消耗: 608K, 提交时间: 2020-09-05 18:30:47

#include<bits/stdc++.h>
using namespace std;
long long n;
int p;
int k;
int a[110];
int mn=2;
struct matrix
{
	int f[101][101];
	void clear(){memset(f,0,sizeof(f));}
	matrix operator * (const matrix a)const
	{
		matrix c; c.clear();
		for(int i=1;i<=mn;i++)
			for(int j=1;j<=mn;j++)
				for(int k=1;k<=mn;k++)
					c.f[i][k]=(1ll*f[i][j]*a.f[j][k]+c.f[i][k])%p;
		return c;
	}
}x,ans;
int qp(int x,long long k)
{
	int res=1;
	for(;k;k>>=1,x=1ll*x*x%p)
		if(k&1)
			res=1ll*res*x%p;
	return res;
}
int main()
{
	scanf("%lld%d",&n,&p);
	scanf("%d",&k);
	for(int i=1;i<=k;i++)
		scanf("%d",&a[i]),mn=max(mn,a[i]);
	for(int i=1;i<=k;i++)
		x.f[mn-a[i]+1][mn]=1;
	for(int i=2;i<=mn;i++)
		x.f[i][i-1]=1;
	ans.f[1][mn]=1;
	long long m=n;
	for(;m;m>>=1,x=x*x)
		if(m&1)
			ans=ans*x;
	printf("%d\n",(qp(2,n-1)-ans.f[1][mn]+p)%p);
	return 0;
}

上一题