2019.10.1 qbxt模拟题

第一题

考虑树上\(DP\),f[i][j][0/1]表示以\(i\)为根的子树,入读为零点的个数为\(j\),点\(i\)的入度为\(0\)/不为\(0\)时的方案数

转移的时候考虑\(u\)的一个子树\(v\)的贡献,分类讨论边\((u,v)\)的两个方向的两个方案,具体的转移方程看代码

记录子树size,利用“刷表法”,只进行有用的转移,复杂度\(O(n^2)\)

#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;

const int MAXN=5010;
const int MOD=1000000007;
const int ch_top=4e7+3;
char ch[ch_top],*now_r=ch-1;

inline int read(){
    while(*++now_r<'0');
    register int x=*now_r-'0';
    while(*++now_r>='0') x=x*10+*now_r-'0';
    return x;
}

int n,m;
LL f[MAXN][MAXN][2];

int Head[MAXN],num;
struct NODE{
    int to,nxt;
} e[MAXN<<1];

inline void add(int x,int y){
    e[++num].to=y;
    e[num].nxt=Head[x];
    Head[x]=num;
}

LL g[MAXN][2];
int sz[MAXN];
inline void dfs(int u,int fa){
    sz[u]=f[u][1][0]=1;
    for(int i=Head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa) continue;
        dfs(v,u);
        for(int j=0;j<=sz[u]+sz[v];++j) g[j][0]=g[j][1]=0;
        for(int j=0;j<=sz[u];++j)
            for(int k=1;k<=sz[v];++k){
                g[j+k-1][1]+=f[u][j][0]*(f[v][k][0]+f[v][k][1]);
                g[j+k-1][1]+=f[u][j][1]*f[v][k][0];
                g[j+k-1][0]+=f[u][j][0]*f[v][k][0];
                g[j+k][1]+=f[u][j][1]*(f[v][k][1]*2+f[v][k][0]);
                g[j+k][0]+=f[u][j][0]*f[v][k][1];
                g[j+k-1][1]%=MOD; g[j+k-1][0]%=MOD;
                g[j+k][0]%=MOD; g[j+k][1]%=MOD;
            }
        for(int j=0;j<=sz[u]+sz[v];++j)
            f[u][j][0]=g[j][0],f[u][j][1]=g[j][1];
        sz[u]+=sz[v];
    }
}

signed main()
{
    fread(ch,1,ch_top,stdin);
    n=read(); m=read();
    if(m>=n){
        puts("0");
        return 0;
    }
    int x,y;
    for(int i=1;i<n;++i){
        x=read(); y=read();
        add(x,y); add(y,x);
    }
    dfs(1,0);
    printf("%lld\n",(f[1][m][1]+f[1][m][0])%MOD);
    return 0;
}
/*
9 4
1 2
2 9
1 3
3 4
3 5
4 8
5 6
5 7

4 2
1 2
1 3
2 4
*/

第二题

不妨设一个数\(x\)为\(1\),可以进行两种操作:

\(x=x<<1\),1的个数不增加,即代价为0

\(x=x<<1|1\),1的个数+1,即代价为1

当x为n的倍数且代价最小时即为答案,考虑最后的答案是一个\(n\)的倍数,不妨利用这个性质,将所有整数对\(n\)取模,其中为0的数可以作为答案,那么问题就转化为了1->0的最短路

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;

const int MAXN=1000010;

inline int read(){
    int x=0; char c=getchar();
    while(c<'0') c=getchar();
    while(c>='0') x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x;
}

int T,n,dis[MAXN];
deque<int> que;

int main()
{
    T=read();
    while(T--){
        n=read();
        memset(dis,0x3f,sizeof(dis));
        dis[1]=1;
        que.clear();
        que.push_back(1);
        while(!que.empty()){
            int u=que.front();
            if(u==0) break;
            que.pop_front();
            int v=u*2%n;
            if(dis[v]>dis[u]){
                dis[v]=dis[u];
                que.push_front(v);
            }
            v=(v+1)%n;
            if(dis[v]>dis[u]+1){
                dis[v]=dis[u]+1;
                que.push_back(v);
            }
        }
        printf("%d\n",dis[0]);
    }
    return 0;
}

第三题

四元环计数模板

类似于三元环计数,考虑将点划分权重,每条边从度数大的点到度数小的点定向,那么一个四元环就会变成这样

灰边的方向有两种情况,但是每个四元环只能从一个点开始遍历找到

爆搜两层就可以了

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int MAXN=100010;

inline int read(){
    int x=0; char c=getchar();
    while(c<'0') c=getchar();
    while(c>='0') x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x;
}

int n,m,du[MAXN];
long long Ans;

int Head[MAXN],num;
struct NODE{
    int to,nxt;
}e[MAXN<<1];

inline void add(int x,int y){
    e[++num].to=y;
    e[num].nxt=Head[x];
    Head[x]=num;
}

inline bool lk(int x,int y){
    return du[x]>du[y]||(du[x]==du[y]&&x>y);
}

int vis[MAXN];

int rt;
inline void dfs(int u,int d){
    if(d==0){
        rt=u;
        for(int i=Head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(lk(rt,v)) dfs(v,d+1);
        }
    }
    else{
        for(int i=Head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(lk(rt,v)){
                Ans+=vis[v];
                ++vis[v];
            }
        }
    }
}

inline void clr(int u,int d){
    if(d==0){
        rt=u;
        for(int i=Head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(lk(rt,v)) clr(v,d+1);
        }
    }
    else for(int i=Head[u];i;i=e[i].nxt)
        ++vis[e[i].to]=0;
}

int main(){
    n=read(); m=read();
    int x,y;
    for(int i=1;i<=m;++i){
        x=read(); y=read();
        add(x,y); add(y,x);
        ++du[y]; ++du[x];
    }
    for(int i=1;i<=n;++i){
        dfs(i,0);
        clr(i,0);
    }
    printf("%lld\n",Ans);
    return 0;
}

原文地址:https://www.cnblogs.com/yjkhhh/p/11792848.html

时间: 2024-11-09 01:15:25

2019.10.1 qbxt模拟题的相关文章

2019.10.30 csp-s模拟测试94 反思总结

头一次做图巨的模拟题OWO 自从上一次听图巨讲课然后骗了小礼物以后一直对图巨印象挺好的233 T1: 对于XY取对数=Y*log(x) 对于Y!取对数=log(1*2*3*...*Y)=log1+log2+log3+...+logY 因为数字大小不超过1e5,直接累加最后比较就可以了 #include<iostream> #include<cstdio> #include<cmath> using namespace std; int t,x,y; double a,b

10.9 guz模拟题题解

感谢@guz 顾z的题题解 考试共三道题,其中 第一题help共10个测试点,时间限制为 1000ms,空间限制为 256MB. 第二题escape共20个测试点,时间限制为1000ms2000ms,空间限制1MB16MB. 第三题cure共20个测试点,时间限制为 1000ms,空间限制为 256MB. PS:题目背景与题目本身无关,可跳过 help 题目背景 在梦中,王 小 呆 到了一个神秘的地方.这里是昆虫王国!国王见王 小 呆 好生俊俏,便给了他一杯昆虫国的老白干.王 小 呆一口下肚,突

2019/10/17 CSP模拟 总结

T1 补票 Ticket 没什么好说的,不讲了 T2 删数字 Number 很后悔的是其实考场上不仅想出了正解的方程,甚至连优化都想到了,却因为码力不足只打了\(O(n^2)\)暴力,甚至还因为细节挂成了\(40\ pts\) 以后还是应该多写一下码农题 规定一下,下面的\(j\)没有特殊说明,取值范围默认在\(1, i - 1\) 考虑什么情况是合法的,首先最后对答案有贡献的元素组成的序列一定是严格上升的,即\(a_i > a_j\) 然后考虑还有没有别的限制呢 放一个图 看到我们的对答案有贡

2019/10/3 CSP-S 模拟测

T1 Permut 题意: 求\(1 - n\)的排列中逆序对数量为\(k\)的排列的个数 SOL: 排除法我们知道一定不是\(O(n!)\)的算法 考虑\(dp\),现在已经有\(n-1\)的答案了,考虑新加入一个数产生多少新的逆序对 设\(dp[i][j]\)表示\(1 -i\)的排列有\(j\)个逆序对的数量,考虑新加入的数插在哪里会增加多少逆序对数量 有\[dp[i][j] = \sum\limits ^{min(i - 1, j)}_k dp[i - 1][j - k]\] 看起来有点

2019.10.21 csp-s模拟测试81 反思总结

T1: 把每一行状压,按行DP.设fi,j,k,i表示第几行,j是当前行的1覆盖状态,k是当前行选择按钮的状态.转移的时候枚举j和k,再枚举下一层的按钮选择情况l.如果l和j可以全覆盖当前层则转移合法,根据下一层选择l状态的代价进行转移.预处理一行每一种选法i可以覆盖到的状态di,各行选择按钮状态i对应的代价dpi,以及每一行的初始状态bi.转移时下一层的覆盖情况就是k|dl|bi+1.初始化第一层是所有选法i对应的代价,即f1,d[i]|b[1],i=dp1,i. 整个DP过程的复杂度是O(3

2019.10.22 csp-s模拟测试82 反思总结

算了 我在干什么orz T2: #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1e5+10,p=1500007,mod=998244353; int n,len,cnt1=1,cnt2=1,lens; char s[2*N],c[2*N]; int tree1[2*N][27],tree2[2*N][27]; unsigned long lon

2019.10.26 csp-s模拟测试88 反思总结

今天的主人公是什么? 60.1K!!!! 先扔代码再更新防止我等会儿一上头不打算写完题解 T1: #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const double inf=214748364; int n,k; double a[100010],f[21][100010]; int main() { scanf("%d%d",&n

更新 | 2019年9月计算机二级office模拟题库

随着2019年上半年计算机二级考试的完美落幕,紧接着的便是9月份的考试了. 到目前为止,下半年9月份计算机二级考试报名开通时间在6月前后,现在也基本结束. 2019年9月(56次)全国计算机等级考试(以下简称NCRE)将于9月中旬举行.已经报名的同学请利用暑期时间好好准备吧! > 2019年9月份最新二级题库看文末 ▼ 公众号内回复关键词:2305获取下载链接 考前学习 计算机二级考试方法为机考,时间为120分钟,分数100分.得60分以上则通过考试. || 好好打基础,温习知识点 不管是自学考

阿里云云计算认证ACP模拟考试练习题第6套模拟题分享(共10套)

阿里云认证考试包含ACA.ACP.ACE三种认证类型,报名考试最多的是ACP认证考试,本人整理了100道全真阿里云ACP认证考试模拟试题,适合需要参加阿里云ACP认证考试的人复习,模拟练习.此为第6套模拟题分享. 阿里云云计算认证ACP模拟考试练习题6 认证级别 云计算 大数据 云安全 中间件 助理工程师(ACA) 云计算助理工程师认证报名入口 大数据助理工程师认证报名入口 云安全助理工程师认证报名入口 专业工程师(ACP) 云计算工程师认证报名入口 大数据工程师认证报名入口 大数据分析师认证报