蓝桥杯真题训练 五一 4/5

1217 垒骰子

矩阵快速幂
op[i]表示的是与i的对面的数。
如果有面互斥,就在矩阵中标记为零,否则标记为4,代表顶和底确定的时候可以有四种情况。(矩阵乘法)
就是快速幂里面的乘法变成了矩阵乘法。

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
typedef long long ll;
const int maxn=6;
ll n,m;
int a,b;
int vis[7][7];
int op[]={3,4,5,0,1,2};
void mul(int c[],int a[],int b[][maxn]){
    int temp[maxn]={0};
    for(int i=0;i<maxn;i++){
        for(int j=0;j<maxn;j++){
            temp[i]=(temp[i]+(ll)a[j]*b[j][i])%mod;
        }
    }
    memcpy(c,temp,sizeof(temp));
}
void mull(int c[][maxn],int a[][maxn],int b[][maxn]){
    int temp[maxn][maxn]={0};
    for(int i=0;i<maxn;i++){
        for(int j=0;j<maxn;j++){
            for(int k=0;k<maxn;k++){
                temp[i][j]=(temp[i][j]+(ll)a[i][k]*b[k][j])%mod;
            }
        }
    }
    memcpy(c,temp,sizeof(temp));
}
int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        cin>>a>>b;
        vis[a-1][b-1]=vis[b-1][a-1]=1;
    }
    int f[maxn]={4,4,4,4,4,4};
    int a[maxn][maxn];
    for(int i=0;i<maxn;i++){
        for(int j=0;j<maxn;j++){
            if(vis[j][op[i]]) a[j][i]=0;
            else a[j][i]=4;
        }
    }
    n--;
    while(n){
        if(n&1) mul(f,f,a);
        mull(a,a,a);
        n>>=1;
    }
    int res=0;
    for(int i=0;i<maxn;i++){
        res=(res+f[i])%mod;
    }
    cout<<res;
    //system("pause");
    return 0;
}

1221 四平方和

用了万能头,hash居然是关键字,这题算是巧妙暴力了,第一次循环的i,j相当于算出了c,d,第二次循环的i,j相当于在循环a,b,因为用 t=n-ixi-jxj 的式子是倒着推的,t一定一开始是大的,所以把当前的i,j当成小的,即a,b,然后has里面存的是i的值+1,再拿出来即可,另一个 d = s q r t ( n − a ∗ a − b ∗ b − c ∗ c ) d=sqrt(n-a*a-b*b-c*c) d=sqrt(naabbcc)通过计算得到答案即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e6+100;
int has[maxn];
int n;
int main(){
    cin>>n;
    for(int i=0;i*i<=n;i++){
        for(int j=i;j*j+i*i<=n;j++){
            if(!has[i*i+j*j]){
                has[i*i+j*j]=i+1;
            }
        }
    }
    for(int i=0;i*i<=n;i++){
        for(int j=0;j*j+i*i<=n;j++){
            int t=n-i*i-j*j;
            if(has[t]){
                int c=has[t]-1;
                int d=(sqrt(t-c*c));
                printf("%d %d %d %d",i,j,c,d);
                return 0;
            }
        }
    }
}

1220 生命之树

这题有坑。。
后面说好的有向图。
定义的时候又是这么一手。相邻两点间有一条边相连的点集,就算。
在这里插入图片描述那不就算无向图嘛。。
按无向图做,找个起点进去搜,定一个父节点保证不搜回去,死在里面。
然后一直搜到叶子节点,再不断回溯回来,回溯的过程中决定选或者不选,最后维护出一个最大的结果。
(这就是树形dp吗)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
ll w[maxn];
vector<int> ve[maxn];
int n;
ll dp[maxn];
void dfs(int x,int fa){
    dp[x]=w[x];
    for(int i=0;i<ve[x].size();i++){
        if(ve[x][i]==fa) continue;
        dfs(ve[x][i],x);
        dp[x]=max(dp[x],dp[x]+dp[ve[x][i]]);
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&w[i]);
    }
    int u,v;
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        ve[u].push_back(v);
        ve[v].push_back(u);
    }
    dfs(1,-1);
    ll ans=dp[1];
    for(int i=2;i<=n;i++) ans=max(ans,dp[i]);
    cout<<ans;
    system("pause");
    return 0;
}
总结:

五一该结束了,因为是广西省,蓝桥杯比第二场,所以还在准备当中。
到此为止也把古老的四五六届的真题写了一遍,感觉比区域赛铜牌题要亲切一些,也算是给每个算法打一个小基础,之前也了解过记忆化搜索,树状数组,还有DP,但是都是一知半解,这几天通过这些比较温柔的题目做了一个很好的吸收,对这些的算法理解更深刻了,对回溯理解也更深刻了。就连全排列也不仅用next_permutation了,又学了一手深搜的全排列,当然有局限性,还有STL里的hash,unordered_set等等。
明天是放假的最后一天,把这届第一场的真题补完(七八九十,十一之前都有写过)。然后该去补作业去了,该死的拖延症。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值