自己出的水题的题解

小小地整理一下我近几天(周)出的题……也不算特别难吧

戳我,我是题目链接

小小的写一下\(\rm{Solution}\)

\(T1:\)

显然是个递推,我们思考第一个情况,对于新加进来的一个物体,他要么自成一圈,要么加入到剩下的空里面。而\(n-1\)个物品的圆排列总共有\(n-1\)个空隙。所以:

我们用\(f_{i,j}\)表示\(i\)个物体,组成\(j\)个圆排列的方案数。那么这个东西的转移就是

\(f_{i,j} = f_{i-1,j - 1} + (i - 1) \times f_{i - 1,j}\)

哦对,说一下,圆排列本质相同的定义是通过自身旋转可以得到的所有排列,与自身本质相同——注意是旋转而不是对称

第二个就更简单了吧,新加进来的物体,要么加入到以前的\(j-1\)个集合里面,要么就直接自成一集合。所以递推式为:

\(f_{i, j} = f_{i - 1,j-1} + j \times f_{i-1,j}\)

#include <cstdio>
#include <iostream>
#define MAX 7010
#define ll long long
#define Mod 993244853

using namespace std ; string Mark ;
int S[MAX][MAX], s[MAX][MAX], i, j, q, Last, Max, N, K ;

inline ll power(ll A, ll B){
    ll Ans = 1 ;
    while(B){
        if (B & 1) Ans = (long long)Ans * (long long)A % Max ;
        A = (long long)A * (long long)A % Max, B >>= 1 ;
    } return Ans ;
}
int main(){
    cin >> Max >> q ; Last = 1, s[0][0] = S[0][0] = 1 ;
    for (i = 1 ; i <= Max ; ++ i)
        for (j = 1 ; j <= Max ; ++ j)
            S[i][j] = ((long long)S[i - 1][j - 1] + (long long)j * (long long)S[i - 1][j] % Mod) % Mod,
            s[i][j] = ((long long)s[i - 1][j - 1] + (long long)(i - 1) * (long long)s[i - 1][j] % Mod) % Mod;
    while(q --){
        cin >> Mark ; scanf("%d%d", &N, &K) , N = power(N, Last + 1) + 1, K %= N, ++ K ;
        if (Mark[0] == 'A') printf("%d\n", Last = s[N][K]) ; else printf("%d\n", Last = S[N][K]) ;
    } return 0 ;
}

\(T2:\)

题目其实就是在求树上的最小点覆盖(染色)和最小边覆盖(染色),\(Idea\)来源于消防局设立那道题。

对于最小点覆盖,思考一个贪心,我们如果从底向上找点进行染色,那么我们一定想要找到的是深度小的点,因为它永远不会更差。所以说,我们考虑先按深度从大到小排一遍序,然后从头扫一遍所有的点。如果从他到他的\(R\)级祖先有被染色的,那么就不需要考虑;否则我们讲其\(R\)级祖先染色,然后用\(R\)级祖先向根节点方向染色。

对于最小边覆盖,在这里我要向我机房的同僚们郑重地道歉——当时我眉飞色舞地讲的\(std\),他是错的。之所以当时讲“不用向上传递”,原因是Luogu上有一道题,也是边覆盖(\(R = 1\)),但是它是单向边!即路径只允许从根到叶子,染色也是单向的,只能从父亲染色到儿子,所以误导了我……2333

那么对于最小边覆盖,我们要做得其实很简单,只需要把边转移到深度较大的节点上,做点覆盖 即可。别忘了特判根节点是不应该算在内的。并且向上传递的时候,不应该算\(R\)级祖先——因为我们的边是存在深度大的节点上的。

那么就做完了,代码细节大概就是我通过记录离点\(u\)最近的、染完色的点与\(u\)的距离。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define min Min
#define MAX 20010
#define Inf 19260817

using namespace std ;
struct Edge{
    int to, next ;
}E[MAX] ; int cnt, head[MAX] ;
int R, i, j, FF, LastF, A, B ; char Mark ;
int Ans, N, M, F[MAX], dep[MAX], T[MAX], dist[MAX]  ;

inline bool Compare(int A, int B){ return dep[A] > dep[B] ;}
inline int Min(int a, int b) {return a & ((a - b) >> 31) | b & (~ (a - b) >> 31) ;}
inline void _Add(int u, int v){
    E[++ cnt].to = v, E[cnt].next = head[u], head[u] = cnt ;
    E[++ cnt].to = u, E[cnt].next = head[v], head[v] = cnt ;
}
inline void Build(int now, int f){
    F[now] = f, dep[now] = dep[f] + 1 ;
    for (int k = head[now] ; k ; k = E[k].next)
        if (E[k].to == f) continue ; else Build(E[k].to, now) ;
}
inline void Init(){
    scanf("%d%d", &N, &R), Ans = 0 ;
    memset(head, 0, sizeof(head)), cnt = 0 ;
    for (i = 0 ; i <= N ; ++ i) T[i] = i, dist[i] = N ;
    for (i = 1 ; i < N ; ++ i) scanf("%d%d", &A, &B), _Add(A, B) ;
    Build(1, 0), sort(T + 1, T + N + 1, Compare) ;
}
int main(){
    scanf("%d", &M) ;
    while(M --){
        cin >> Mark ; Init() ;
        if (Mark == 'A'){
            for (i = 1 ; i <= N ; ++ i){
                FF = F[T[i]] ;
                for (j = 1 ; j <= R ; ++ j)
                    dist[T[i]] = min(dist[T[i]], dist[FF] + j), LastF = FF, FF = F[FF] ;
                FF = LastF ; if (dist[T[i]] <= R) continue ;
                dist[FF] = 0, ++ Ans ; for (j = 0 ; j <= R ; ++ j) dist[FF] = j, FF = F[FF] ;
            }
            printf("%d\n", Ans) ;
        }
        else {
            for (i = 1 ; i <= N ; ++ i){
                if (T[i] == 1) continue ;
                FF = F[T[i]] ;
                for (j = 1 ; j <= R ; ++ j)
                    dist[T[i]] = min(dist[T[i]], dist[FF] + j), LastF = FF, FF = F[FF] ;
                FF = LastF ; if (dist[T[i]] <= R) continue ; dist[FF] = 0 ;
                for (j = 0 ; j < R ; ++ j) dist[FF] = j, FF = F[FF] ; ++ Ans ;//此处与点覆盖有区别
            }
            printf("%d\n", Ans) ;
        }
    }
    return 0 ;
}

\(T3\)

大概在这里吧:\(Link\)

\(\rm{Code}\)

#include <stack>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

#define MAXB 2010
#define MAXD 5010
#define MAXN 1000010
#define MAXC 6001000
#define Inf 1e17
#define LL long long

char Mark ;

using namespace std ;

namespace pksA{
    #define ls(rt) rt << 1
    #define rs(rt) rt << 1 | 1
    #define  Mid  ((L + R) >> 1)

    struct Tree{
        LL M[2] ;
        Tree(){M[0] = M[1] = Inf ;}
    }T[MAXN << 2] ; int N, Len, rank[MAXN] ;
    LL base[MAXN], t[MAXN], i, j, k, dp[MAXN] ;     

    template<class T> inline void Make_min(T &x, T &y){ x > y ? x = y : x = x ; }

    inline LL Min(LL A, LL B){ return A & ((A - B) >> 63) | B & (~(A - B) >> 63) ;}

    inline void push_up(int rt){
        T[rt].M[0] = Min(T[ls(rt)].M[0], T[rs(rt)].M[0]) ;
        T[rt].M[1] = Min(T[ls(rt)].M[1], T[rs(rt)].M[1]) ;
    }
    inline void update(int rt, int L, int R, int pos, LL M0, LL M1){ //BIT Insert
        if (L == R){
            Make_min(T[rt].M[0], M0) ;
            Make_min(T[rt].M[1], M1) ;
            return ;
        }
        if (pos <= Mid) update(ls(rt), L, Mid, pos, M0, M1) ;
        else update(rs(rt), Mid + 1, R, pos, M0, M1) ; push_up(rt) ;
    }
    inline LL query(int rt, int L, int R, int ql, int qr, bool Mark){
        if (ql > qr) return Inf ;
        if (ql <= L && R <= qr) return T[rt].M[Mark] ;
        LL res = Inf ;
        if (ql <= Mid) res = Min(res, query(ls(rt), L, Mid, ql, qr, Mark)) ;
        if (qr > Mid) res = Min(res, query(rs(rt), Mid + 1, R, ql ,qr, Mark)) ;
        return res ;
    }
    void SolveA(){
        cin >> N ; dp[1] = Inf ; rank[N + 1] =  0x3f ;
        for (i = 1 ; i <= N ; ++ i)
            scanf("%lld", &base[i]), t[i] = base[i] ;
        sort(t + 1, t + N + 1) ;//discretization
        Len = unique(t + 1, t + N + 1) - t - 1 ;
        for (i = 1 ; i <= N ; ++ i)
            rank[i] = lower_bound(t + 1, t + Len + 1, base[i]) - t ;
        for (i = 2 ; i <= N ; ++ i){//dp
            update(1, 1, Len, rank[i - 1], dp[i - 2] - base[i - 1], dp[i - 2] + base[i - 1]) ;
            dp[i] = Min(query(1, 1, Len, 1, rank[i], 0) + base[i],  query(1, 1, Len, rank[i] + 1, Len, 1) - base[i]) ;
        }
        cout << dp[N] << endl ;  // by Flower_pks
    }
}
namespace pksB{
    stack <int> s ;
    int N, Len, L[11] ;
    int i, j, k, di, dj ;
    int temp[MAXB][MAXB] ;
    char S[MAXB], M[11][MAXB] ;
    int Ans, dp[MAXB][MAXB], T ;
    void SolveB(){
        cin >> (S + 1), cin >> N, Len = strlen(S + 1) ;
        for (i = 1 ; i <= N ; ++ i) cin >> (M[i] + 1), L[i] = strlen(M[i] + 1) ;
        for (i = 1 ; i <= N ; ++ i){
            memset(dp, 0, sizeof(dp)) ;
            for (j = 1 ; j <= Len ; ++ j)
                for (k = 1 ; k <= L[i] ; ++ k)
                    if (M[i][k] == S[j]) dp[j][k] = dp[j - 1][k - 1] + 1 ;
                    else dp[j][k] = max(dp[j - 1][k], dp[j][k - 1]) ;
            if (Ans < dp[Len][L[i]]){
                Ans = dp[Len][L[i]], T = i ;
                for (di = 1 ; di <= Len ; ++ di)
                    for (j = 1 ; j <= L[i] ; ++ j)
                        temp[di][j] = dp[di][j] ;
            }
        }
        for (i = Len ; i >= 1 ; -- i){
            if (s.size() == Ans) break ;
             for (j = L[T] ; j >= 1 ; -- j)
                if (temp[i][j] != temp[i - 1][j] && temp[i][j] != temp[i - 1][j]){
                    s.push(i) ; break ;
                }
        }
        cout << Ans << endl ; while (!s.empty()) printf("%c", S[s.top()]), s.pop() ;
    }
}
namespace pksC{
    #define Mod 998244853
    int N, M, i, j, k ;
    LL Sum[MAXC], F[MAXC] ;
    void SolveC(){
        scanf("%d%d", &N, &M) ;
        Sum[0] = F[0] = M + 1 ;
        for (i = 1 ; i <= N ; ++ i)
            F[i] = (Sum[i - 1] + M + 1) % Mod,
            Sum[i] = (Sum[i - 1] + F[i]) % Mod;
        printf("%lld", F[N]) ;
    }
    #undef Mod
}
namespace pksD{
    #undef Inf
    #define Inf 1e30
    int i, j, k ;
    struct Nodes{
        double x, y ;
    }base[MAXD << 1] ;
    int N ; double dp[MAXD][MAXD], Ans ;
    inline bool Compare(Nodes A, Nodes B){
        return A.x < B.x ;
    }
    inline double dis(int x, int y){
        return sqrt((base[x].x - base[y].x) * (base[x].x - base[y].x)
            + (base[x].y - base[y].y) * (base[x].y - base[y].y)) ;
    }
    void SolveD(){
        cin >> N ;
        for (i = 1 ; i <= N ; ++ i)
            scanf("%lf%lf", &base[i].x, &base[i].y) ;
        sort(base + 1, base + N + 1, Compare) ;
        for (i = 1 ; i <= N ; ++ i)
            for (j = 1 ; j <= N ; ++ j)
                dp[i][j] = Inf * Inf ; Ans = Inf * Inf ;
        dp[1][2] = dis(1, 2) ;
        for (i = 1 ; i < N ; ++ i)
            for (j = i + 1 ; j <= N ; ++ j)
                dp[i][j + 1] = min(dp[i][j + 1], dp[i][j] + dis(j, j + 1)),
                dp[j][j + 1] = min(dp[j][j + 1], dp[i][j] + dis(i, j + 1)) ;
        for(i = 1 ; i < N ; ++ i)
            Ans = min(Ans, dp[i][N] + dis(i, N));
        printf("%.2lf", Ans) ;
    }
}
int main(){
    cin >> Mark ;
    if (Mark == 'A') pksA :: SolveA() ;
    else if (Mark == 'B') pksB :: SolveB() ;
    else if (Mark == 'C') pksC :: SolveC() ;
    else pksD :: SolveD() ; return 0 ;
}

原文地址:https://www.cnblogs.com/pks-t/p/9931993.html

时间: 2024-10-09 15:30:33

自己出的水题的题解的相关文章

hdu--2191--终于可以说出dp水题这句话了-.-

这题是 上一题的 recommend 过来的 很水.. 虽然是多重背包 但是 因为数据太小了 完全可以不用二进制拆分去做 我两者都去写了下 ...都是0ms.. 1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int size = 110; 7 int weight[size*20]; 8 int val[size*20]

bzoj usaco 金组水题题解(1)

UPD:我真不是想骗访问量TAT..一开始没注意总长度写着写着网页崩了王仓(其实中午的时候就时常开始卡了= =)....损失了2h(幸好长一点的都单独开了一篇)....吓得赶紧分成两坨....TAT.............. —————————————————————————————————————————————————————————————————————————————— 写(被虐)了整整一个月b站上usaco的金组题...然而到现在总共只写了100道上下TAT(当然是按AC人数降序排

ytu 1061: 从三个数中找出最大的数(水题,模板函数练习 + 宏定义练习)

1061: 从三个数中找出最大的数Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 154  Solved: 124[Submit][Status][Web Board] Description 定义一个带参的宏(或者模板函数),从三个数中找出最大的数. Input 3个短整型数,空格隔开 3个实数,空格隔开 3个长整数,空格隔开 Output 最大的数,对于实数保留2位小数. Sample Input 1 2 3 1.5 4.7 3.2 123456

【省选水题集Day1】一起来AK水题吧! 题解(更新到A)

题目:http://www.cnblogs.com/ljc20020730/p/6937936.html 水题A:[AHOI2001]质数和分解 安徽省选OI原题!简单Dp. 一看就是完全背包求方案数! 完全背包都会打吧,原来是最优值,现在是累计值. 状态转移方程:f[j]=f[j]+f[j-w[i]],w[i]是待选质数. 理解:一个数要拆成若干素数和,等同于拆成所有该数减去一个素数差的方案数之和(而不是最优方案数) 但这么做需要初始化为0,同时用滚动数组可以减小时间和空间复杂度. 代码如下:

PAT甲题题解-1011. World Cup Betting (20)-误导人的水题。。。

题目不严谨啊啊啊啊式子算出来结果是37.975样例输出的是37.98我以为是四舍五入的啊啊啊,所以最后输出的是sum+0.005结果告诉我全部错误啊结果直接保留两位小数就可以了啊啊啊啊 水题也不要这么坑人啊啊啊啊 #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int main() { double a[3];

PAT甲题题解-1012. The Best Rank (25)-排序水题

排序,水题因为最后如果一个学生最好的排名有一样的,输出的课程有个优先级A>C>M>E那么按这个优先级顺序进行排序每次排序前先求当前课程的排名然后再与目前最好的排名比较.更新 至于查询,建立id与索引的映射即可. #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <map> using namespace s

PAT甲题题解-1019. General Palindromic Number (20)-又是水题一枚

n转化为b进制的格式,问你该格式是否为回文数字(即正着写和倒着写一样)输出Yes或者No并且输出该格式又是水题... #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn=30; int a[maxn]; int n,b; int main() { scanf("%d %d&q

PAT甲题题解-1050. String Subtraction (20)-水题

#include <iostream> #include <cstdio> #include <string.h> #include <algorithm> using namespace std; /* 水题,注意字符范围是整个ASCII编码即可. */ const int maxn=130; int vis[maxn]; char s1[10000+5]; char s2[10000+5]; int main() { gets(s1); //getcha

4.7-4.9补题+水题+高维前缀和

题目链接:51nod 1718 Cos的多项式  [数学] 题解: 2cosx=2cosx 2cos2x=(2cosx)^2-2 2cos3x=(2cosx)^3-3*(2cosx) 数归证明2cos(nx)能表示成关于2cosx的多项式,设为f(n) f(1)=x,f(2)=x^2-2(其中的x就是2cosx) 假设n=1~k时均成立(k>=3) 当n=k+1时 由cos((k+1)x)=cos(kx)cos(x)-sin(kx)sin(x) cos((k-1)x)=cos(kx)cos(x)