zoukankan      html  css  js  c++  java
  • 7.15 集训总结

    A、数列

    题目描述


    分析

    非常显然的矩阵快速幂
    首先我们要构造如下的两个矩阵
    (left[ egin{matrix} b &c &d &1\1 &0 &0 &0\ 0 &1 &0 &0\0 &0 &0 &1end{matrix} ight])

    (left[ egin{matrix} a_2 &0 &0 &0\a_1 &0 &0 &0\ a_0 &0 &0 &0\e &0 &0 &0end{matrix} ight])

    然后做矩阵乘法就可以了

    要注意的是,矩阵乘法不满足交换律,所以哪一行哪一列相乘一定要搞清

    而且比较恶心的是,由于模数为(10^{18}),所以两个数相乘会爆(long long),因此在做乘法的时候还要用到高精度

    考试的时候写完矩阵快速幂又写了一个暴力的对拍,却一直出错

    后来输出中间变量才发现是暴力溢出了,最后5分钟才交上

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ll;
    const ll mod=1000000000000000000;
    struct jz{
        ll sz[10][10];
        jz(){
            memset(sz,0,sizeof(sz));
        }
    }now,ans;
    ll jla[100],jlb[100],jg[100];
    ll wdcf(ll aa,ll bb){
        memset(jla,0,sizeof(jla));
        memset(jlb,0,sizeof(jlb));
        ll cnta=0,cntb=0;
        while(aa){
            jla[++cnta]=aa%10;
            aa/=10;
        }
        while(bb){
            jlb[++cntb]=bb%10;
            bb/=10;
        }
        memset(jg,0,sizeof(jg));
        for(ll i=1;i<=cnta;i++){
            for(ll j=1;j<=cntb;j++){
                jg[i+j-1]+=jla[i]*jlb[j];
            }
        }
        ll mans=0,jl=1;
        for(ll i=1;i<=19;i++){
            if(jg[i]>=10){
                ll zj=jg[i]/10;
                jg[i+1]+=zj;
                jg[i]%=10;
            }
            mans+=jg[i]*jl;
            jl*=10;
        }
        return mans;
    }
    jz cf(jz aa,jz bb){
        jz cc;
        memset(cc.sz,0,sizeof(cc.sz));
        for(int i=1;i<=4;i++){
            for(int j=1;j<=4;j++){
                for(int k=1;k<=4;k++){
                    cc.sz[i][j]=(cc.sz[i][j]%mod+wdcf(aa.sz[i][k],bb.sz[k][j])%mod)%mod;
                }
            }
        }
        return cc;
    }
    int num[50],cnt=0;
    int main(){
        ll a0,a1,a2,b,c,d,e,n;
        scanf("%llu%llu%llu%llu%llu%llu%llu%llu",&a0,&a1,&a2,&b,&c,&d,&e,&n);
        ans.sz[1][1]=a2%mod;
        ans.sz[2][1]=a1%mod;
        ans.sz[3][1]=a0%mod;
        ans.sz[4][1]=e%mod;
        now.sz[1][1]=b%mod;
        now.sz[1][2]=c%mod;
        now.sz[1][3]=d%mod;
        now.sz[1][4]=1;
        now.sz[2][1]=1;
        now.sz[3][2]=1;
        now.sz[4][4]=1;
        ll jg;
        if(n==0) jg=a0;
        else if(n==1) jg=a1;
        else if(n==2) jg=a2;
        else {
            ll zs=n-2;
            while(zs){
                if(zs&1) ans=cf(now,ans);
                now=cf(now,now);
                zs>>=1;
            }
            jg=ans.sz[1][1]%mod;
        }
        while(jg){
            num[++cnt]=jg%10;
            jg/=10;
        }
        int dy=18-cnt;
        for(int i=1;i<=dy;i++){
            printf("0");
        }
        printf("%llu
    ",ans.sz[1][1]%mod);
        return 0;
    }
    
    

    B、旗木双翼

    题目描述




    分析

    很有思维含量的一道题
    我们可以把题意转换成一个人从坐标为((n,m))的开始走,走到坐标为((0,0))的点
    而且只能向上向右走的方案数
    看下面的图可能会更好理解一些

    因此最终的结果就是(C_{n+m}^{n})
    因为结果要取模,而且涉及到除法运算,因此要求逆元

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=200005;
    ll ny[maxn];
    int main(){
        ll n,m;
        scanf("%lld%lld",&n,&m);
        ny[1]=1;
        for(ll i=2;i<=n+m;i++){
            ny[i]=(mod-mod/i)*ny[mod%i]%mod;
        }
        ll ans=1;
        for(ll i=1;i<=n+m;i++){
            ans=ans*i%mod;
        }
        for(ll i=1;i<=n;i++){
            ans=ans*ny[i]%mod;
        }
        for(ll i=1;i<=m;i++){
            ans=ans*ny[i]%mod;
        }
        printf("%lld
    ",ans%mod);
        return 0;
    }
    

    C、乌龟棋

    题目描述




    分析

    我们设(f[a][b][c][d])为使用了(a)张标有数字(1)的卡片,(b)张标有数字(2)的卡片,(c)张标有数字(3)的卡片,(d)张标有数字(4)的卡片所能得到的最大得分
    状态转移方程就很显然了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 45;
    int f[maxn][maxn][maxn][maxn];
    const int N = 400;
    int nn[N],mm[N];
    int n,m;
    int sum[maxn];
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&nn[i]);
    	}
    	for(int i=1;i<=m;++i){
    		scanf("%d",&mm[i]);
    		sum[mm[i]]++;
    	}
    	for(int a=0;a<=sum[1];++a){
    		for(int b=0;b<=sum[2];++b){
    			for(int c=0;c<=sum[3];++c){
    				for(int d=0;d<=sum[4];++d){
    					int jl1=0,jl2=0,jl3=0,jl4=0;
    					if(a)jl1=f[a-1][b][c][d];
    					if(b)jl2=f[a][b-1][c][d];
    					if(c)jl3=f[a][b][c-1][d];
    					if(d)jl4=f[a][b][c][d-1];
    					f[a][b][c][d]=max(max(jl1,jl2),max(jl3,jl4))+nn[a+2*b+3*c+4*d+1];
    				}
    			}
    		}
    	}
    	printf("%d
    ",f[sum[1]][sum[2]][sum[3]][sum[4]]);
    	return 0;	
    }
    

    D、假面舞会

    题目描述



    分析

    传送门

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+5;
    int head[maxn],tot=2;
    struct asd{
    	int from,to,next,val;
    }b[maxn];
    void ad(int aa,int bb,int cc){
        b[tot].from=aa;
        b[tot].to=bb;
        b[tot].next=head[aa];
        b[tot].val=cc;
        head[aa]=tot++;
    }
    bool vis[maxn];
    int dis[maxn],ans;
    void DFS(int now){
        vis[now]=1;
        for (int i=head[now];i!=-1;i=b[i].next){
    		int u=b[i].to;
    		if(!vis[u]){
    			dis[u]=dis[now]+b[i].val;
    			DFS(u);
    		} else {
                if(ans==0) ans=abs(dis[now]+b[i].val-dis[u]);
    			else ans=__gcd(ans,abs(dis[now]+b[i].val-dis[u]));
    		}
    	}
    }
    int mmin,mmax;
    int jud[maxn];
    void dfs(int now){
        mmax=max(mmax,dis[now]);
        mmin=min(mmin,dis[now]);
        vis[now]=1;
        for(int i=head[now];i!=-1;i=b[i].next){
            if(!jud[i]){
                jud[i]=jud[i^1]=1;
                int u=b[i].to;
                dis[u]=dis[now]+b[i].val;
                dfs(u);
            }
        }
    }
    int main(){
        memset(head,-1,sizeof(head));
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int aa,bb;
            scanf("%d%d",&aa,&bb);
            ad(aa,bb,1);
            ad(bb,aa,-1);
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]) DFS(i);
        }
        if(ans){
            if(ans<3) printf("-1 -1
    ");
            else {
                int now;
                for(int i=3;i<=ans;i++){
                    if(ans%i==0) {
                        now=i;
                        break;
                    }
                }
                printf("%d %d
    ",ans,now);
            }
            return 0;
        }
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                mmin=mmax=dis[i]=0;
                dfs(i);
                ans+=mmax-mmin+1;
            }
        }
    	if(ans>=3) printf("%d 3
    ",ans);
    	else printf("-1 -1
    ");
        return 0;
    }
    
  • 相关阅读:
    python,生产环境安装
    neo4j 图数据库
    RNN系列
    机器学习关于AUC的理解整理
    fensorflow 安装报错 DEPENDENCY ERROR
    dubbo Failed to check the status of the service com.user.service.UserService. No provider available for the service
    使用hbase遇到的问题
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk
    gradle 安装
    jenkins 安装遇到的坑
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/13307833.html
Copyright © 2011-2022 走看看