2019寒假wannafly_camp_day8

A题

link

题解:

题意告诉我们一棵bfs序树让我们求每个叶子节点与编号小于其的叶子节点的路径的最小值。
可以想到的是在每个节点中记录一个f数组表示其离最近的叶子节点的距离。
那这样我们只要保证对于每一次枚举叶子节点后更新后的树上的f数组是正确的,在下一次枚举到
时,向上dfs的过程中发现有一个节点被更新过,则该叶子节点的答案就是f[x]+f[pre]+1
但是要注意的是,更新完后我们还要进行一次回溯,因为可能回溯过程中的节点f值是深度较小的叶子节点。因此还要进行一步f[x]=min(f[x],f[y]+1)的操作(wa了6发)

代码:

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef double db;
#define INF 0x3f3f3f3f
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=4e6+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//逆元
int head[N],NEXT[N],ver[N],tot;void link(int u,int v){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;}
int indeg[N],f[N];
bool mark;
int ans;
void dfs(int x,int pre){
    if(f[x]!=-1){
        mark=true;
        ans=f[x]+f[pre]+1;
        return;
    }
    else f[x]=f[pre]+1;
    for(int i=head[x];i;i=NEXT[i]){
        int y=ver[i];
        dfs(y,x);
        f[x]=min(f[x],f[y]+1);
    }
}
int main(){
    int n;
    int u;
    scanf("%d",&n);
    for(int i=2;i<=n;i++){
        scanf("%d",&u);
        link(i,u);
        indeg[u]++;
    }
    memset(f,-1,sizeof(f));
    for(int i=1;i<=n;i++){
        if(indeg[i]) continue;
        mark=false;
        dfs(i,0);
        if(mark){
            printf("%d %d\n",i,ans);
        }
        else {
            printf("%d -1\n",i);
        }
    }

    return 0;
}

D题:

link

题解:

题目大概意思是在 2 n 2n 2n个字中填左空右三个字 其中左右不能连续,空只能连续 2 2 2个一起存在,且左右的个数一样。由于 n n n很小只有 20 20 20,于是想到了一个 5 5 5维的 d p dp dp
dp[i][j][k][p][q] 其中 i i i表示第 i i i位, j j j表示前 i i i位有几个左, k k k表示前 i i i位有几个右, p p p表示当前位置有连续几个空, q q q表示当前位置插入的是左·右·空(1·2·3),然后就可以按题意模拟转移方程了,详见代码

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define MOD 998244353
long long dp[55][50][50][5][5];
int main()
{
    int n;
    scanf("%d",&n);
    dp[1][1][0][0][1] = 1;
    dp[1][0][1][0][2] = 1;
    dp[1][0][0][1][3] = 1;
    for(int i = 2;i<=2*n;i++)
    {
    for(int j = 0;j<=i;j++)
    {
        for(int k = 0;k<=i;k++)
        {
            if(i==2*n&&j!=k) continue;
            if(k+j>i) continue;
            if(j>=1)
            dp[i][j][k][0][1] += dp[i-1][j-1][k][0][1];
            dp[i][j][k][0][1] += dp[i-1][j-1][k][2][3];
            dp[i][j][k][0][1]%=MOD;
            //dbg3(i,j,k);
            //dbg(dp[i][j][k][0][1]);
            if(k>=1)
            dp[i][j][k][0][2] += dp[i-1][j][k-1][0][2] ;
            dp[i][j][k][0][2] += dp[i-1][j][k-1][2][3];
            dp[i][j][k][0][2]%=MOD;
            //dbg(dp[i][j][k][0][2]);
            dp[i][j][k][1][3] += dp[i-1][j][k][0][1]+dp[i-1][j][k][0][2];
            dp[i][j][k][1][3] %= MOD;
            //dbg(dp[i][j][k][1][3]);
            dp[i][j][k][2][3] += dp[i-1][j][k][1][3];
            dp[i][j][k][2][3] %= MOD;
            //dbg(dp[i][j][k][2][3]);
        }
    }
    }
    long long ans = 0;
    for(int i = 0;i<n;++i)
    {
        //dbg(i);
        ans+=dp[2*n][i][i][0][1] + dp[2*n][i][i][0][2] + dp[2*n][i][i][2][3];
        //dbg3(dp[2*n][i][i][0][1] , dp[2*n][i][i][0][2] , dp[2*n][i][i][2][3]);
        ans%=MOD;
    }
    printf("%lld\n",ans);
    return 0;
}

G题:

link

题解:

可以将原题中的i*fi转化成将矩阵分成小块即 1 1 1的个数,于是问题就又变成在 n ∗ m n*m nm的矩阵中值为1的子矩阵个数总和,通俗讲就是假如 ( 1 , 2 ) ( 3 , 3 ) (1,2)(3,3) 1233中值是1,那 a n s ans ans就是包括 ( 1 , 2 ) (1,2) 12的矩阵个数 + + +包括 ( 3 , 3 ) (3,3) 33的矩阵个数。

代码:

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef double db;
#define INF 0x3f3f3f3f
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
const int N=3e5+7,M=2e6;
const long long mod=998244353;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//逆元
//int head[N],NEXT[M],ver[M],tot;void link(int u,int v,ll w){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;wei[tot]=w;}
char str[2200][2200];
int main(){
    ll n,m;
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",str[i]+1);
    }
    ll ans=0;
    for(ll i=1;i<=n;i++){
        for(ll j=1;j<=m;j++){
            if(str[i][j]!='1') continue;
            ans+=(((((i*(n-i+1LL))%mod)*j)%mod)*(m-j+1LL))%mod;
            ans%=mod;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

( 未 完 待 续 ) (未完待续)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值