1. 程式人生 > >焦作網路賽(今天開始ACM康復計劃~)

焦作網路賽(今天開始ACM康復計劃~)

題目在計蒜課上

K:Transport Ship

給n種船,每個船分別可以裝2^n-1個貨物,有S個貨物,問裝S個貨物就幾種裝配方法。

開始想的多元線性迴歸,然後想的暴力,腦子真的蠢,這麼裸的揹包沒一眼看出,補補補補補補補補!!

程式碼:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const long long maxn = 1e5+7;
    const int mod=1e9+7;
    struct ttt{
        int v,num;
    };
    ttt q1[maxn];
    int res[maxn];
    int main(){
        //freopen("in.txt","r",stdin);
        //freopen("out1.txt","w",stdout);
        int i,j,k,f1,f2,f3,t1,t2,t3;
        int T;
        int n,m;
        int l;
        scanf("%d",&T);
        while(T--){
        scanf("%d %d",&n,&m);
        memset(res,0,sizeof(res));
        for(i=1;i<=n;i++){
        scanf("%d %d",&q1[i].v,&q1[i].num);
        }
        res[0]=1;
        for(i=1;i<=n;i++){
            for(j=0;j<q1[i].num;j++){ //因為是2^k-1個,所以取的時候是1/2/4/8/2^(k-1)剛好全部覆蓋
                for(k=10000;k>=q1[i].v;k--){
                    if(k-(1<<j)*q1[i].v<0)break;
                    res[k]+=res[k-(1<<j)*q1[i].v];
                    res[k]%=mod;
                }
            }
        }

        for(i=1;i<=m;i++){
        scanf("%d",&t1);
    //    cout << t1<< endl;
        printf("%d\n",res[t1]);
        }
        }
        return 0;
    }

L:矩陣快速冪(從黃大佬手裡摸了一套超短的快速冪板子

自己找一個遞推公式。

本來一般矩陣快速冪是f[n]=2f[n-1]+3f[n-2]+5f[n-5]的形式,

現在改為f[n]=2g(n-1)+h(n-1)

但是每個g和h又能通過前面的函式推出,那麼這樣子也可以矩陣快速冪列出矩陣

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const long long maxn = 1e5+7;
const int mod=1e9+7;
const int N = 9;
struct Mat{
	ll m[N][N];
	void clear(){memset(m,0,sizeof(m));}
	void I(){for (int i=0;i<N;i++) m[i][i]=1;}
};
Mat mul(const Mat &a, const Mat &b){
	Mat c;c.clear();
	for (int i=0;i<N;i++)
		for (int j=0;j<N;j++){
			for (int k=0;k<N;k++)
				c.m[i][j]+=a.m[i][k]*b.m[k][j]%mod;
			c.m[i][j]%=mod;
		}
	return c;
}
Mat qpow(Mat a, ll x){ //這裡注意傳進來的引數要為long long 不然會報超時
	Mat ans; ans.clear(); ans.I();
	for (;x;a=mul(a,a),x>>=1)
		if (x&1)
			ans=mul(ans,a);
	return ans;
}
Mat t2=(Mat){{
{0,0,0,1,0,0,1,0,0},
{1,0,0,1,0,0,1,0,0},
{1,0,0,1,0,0,0,0,0},
{0,1,0,0,1,0,0,1,0},
{0,1,0,0,0,0,0,1,0},
{0,1,0,0,1,0,0,0,0},
{0,0,1,0,0,0,0,0,1},
{0,0,0,0,0,1,0,0,1},
{0,0,1,0,0,1,0,0,0}
}};

int main(){
        //freopen("in.txt","r",stdin);
        //freopen("out1.txt","w",stdout);
        int i,j,k,f1,f2,f3;
        int T;
        int l;
        ll t1;
        scanf("%d",&T);
        while(T--){
        scanf("%lld",&t1);
        if(t1==1){
        printf("3\n");continue;
        }else if(t1==2){
        printf("9\n");continue;
        }
        Mat t3;
        t3=qpow(t2,t1-2);
        int ans=0;
        for(i=0;i<9;i++)
            for(j=0;j<9;j++){
                ans+=t3.m[i][j];
                ans%=mod;
            }
        printf("%d\n",ans);
        }
        return 0;
}