zoukankan      html  css  js  c++  java
  • AT2371[AGC013E]Placing Squares【矩阵乘法】

    正题

    题目链接:https://www.luogu.com.cn/problem/AT2371


    题目大意

    给出\(n\)\(m\)个数\(b\)
    求所有满足以下要求的序列\(a\)

    1. 和为\(n\)
    2. 对于所有\(b_i\)不存在任何一个前缀和为\(b_i\)

    一个序列的贡献为所有数的二次方和,求所有合法序列的贡献。

    \(1\leq n\leq 10^9,1\leq m\leq 10^5\)


    解题思路

    它要是\(n\)开到\(10^{18}\)我就会了(雾)

    显然地我们是到每个\(m\)处然后容斥,所以如果这么想你就错了

    这个平方很难统计,考虑转换成另一个模型,在分出的每一段中选出两个位置(有序,可重)放上一个红球和一个蓝球,求方案数。

    那么我们就有一个\(dp\)的想法,设\(f_{i,j}\)表示表示目前到第\(i\)个位置,目前最后的一段已经放了\(j\)个球了,当两个球位置不同时的转移乘二即可。

    这样在有限制的位置和没有限制的位置就分别有了两个转移矩阵,分成\(m\)段乘起来就好了。

    时间复杂度:\(O(m\log n)\)


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll S=3,P=1e9+7;
    struct Matrix{
    	ll a[S][S];
    }c,f,g,ans;
    ll n,m;
    Matrix operator*(const Matrix &a,const Matrix &b){
    	memset(c.a,0,sizeof(c.a));
    	for(ll i=0;i<S;i++)
    		for(ll j=0;j<S;j++)
    			for(ll k=0;k<S;k++)
    				(c.a[i][j]+=a.a[i][k]*b.a[k][j]%P)%=P;
    	return c;
    }
    void power(Matrix x,ll b){
    	while(b){
    		if(b&1)ans=ans*x;
    		x=x*x;b>>=1;
    	}
    	return;
    }
    signed main()
    {
    	scanf("%lld%lld",&n,&m);
    	f.a[0][0]=2;f.a[0][1]=1;f.a[0][2]=1;
    	f.a[1][1]=1;f.a[1][2]=2;f.a[1][0]=2;
    	f.a[2][2]=1;f.a[2][0]=1;
    	g=f;g.a[0][0]=1;g.a[1][0]=0;g.a[2][0]=0;
    	ll last=0;ans.a[0][0]=1;
    	for(ll i=1,x;i<=m;i++){
    		scanf("%lld",&x);
    		power(f,x-last-1);
    		ans=ans*g;
    //		ans.a[0][0]*=-1;
    		last=x;
    	}
    	power(f,n-last);
    	printf("%lld\n",ans.a[0][2]);
    	return 0;
    }
    
  • 相关阅读:
    【java】-- java并发包总结
    【Linux】-- Linux上java运行环境的配置(JDK+TOMCAT)
    【Redis】-- 安装及配置
    【redis】-- springboot集成redis及使用
    【写法规范】-- 设计请求返回接口与封装
    每日CSS_发光文本效果
    每日CSS_实时时钟效果
    每日CSS_霓虹灯按钮悬停效果
    CSS3全览_动画+滤镜
    CSS3全览_最新布局
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15616016.html
Copyright © 2011-2022 走看看