zoukankan      html  css  js  c++  java
  • [不堪回首] 自己出的水题的题解

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

    戳我,我是题目链接

    小小的写一下( m{Solution})

    (T1:)

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

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

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

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

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

    (f_{i, j} = f_{i - 1,j-1} + j imes 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
    ", Last = s[N][K]) ; else printf("%d
    ", 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
    ", 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
    ", Ans) ; 
    		}
    	}
    	return 0 ;
    }
    

    (T3)

    大概在这里吧:(Link)

    ( m{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 ;
    }
    
  • 相关阅读:
    php......房屋租赁练习
    php......调研投票练习
    数据访问......单条件查询与多条件查询
    数据访问......简单练习
    数据访问......增删改查
    数据访问
    面向对象练习
    php正则表达式和数组
    php面向对象加载类
    php类和对象(二)
  • 原文地址:https://www.cnblogs.com/pks-t/p/9931993.html
Copyright © 2011-2022 走看看