1. 程式人生 > 實用技巧 >2020.7.27 測試總結&題解

2020.7.27 測試總結&題解

Orz wcy,xxh,zcy,zjl,twx

\(20+100+50=170,rk\ 5\)

A:NOIp 2012 國王遊戲

貪心柿子推對了,結果高精度打炸,\(20\) 分滾粗。

時間複雜度 \(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
int n;
struct zy {
	int l,r;
} gw,dc[1010];
bool cmp(zy _,zy __) {
	return _.l*_.r<__.l*__.r;
}
struct lgs {
	int len;
	int n[10010];
} ;
void write(lgs x) {
	for (int i = x.len; i >= 1; i--)
		cout << x.n[i];
	cout << endl;
}
void mul(lgs x, int y, lgs &z) {
	memset(z.n, 0, sizeof z.n);
	z.len = x.len;
	for (int i = 1; i <= x.len; i++)
		z.n[i] += x.n[i] * y;
	for (int i = 1; i <= z.len; i++)
		if (z.n[i] > 9) {
			z.n[i + 1] += z.n[i] / 10;
			z.n[i] %= 10;
			if (i == z.len) z.len++;
		}
}
void div(lgs x, int y, lgs &z) {
	int q = 0;
	memset(z.n, 0, sizeof z.n);
	z.len = x.len;
	for (int i = x.len; i >= 1; i--) {
		q *= 10;
		q += x.n[i];
		if (q >= y) {
			z.n[i] = q / y;
			q %= y;
		}
	}
	while (!z.n[z.len] && z.len > 1) z.len--;
}
lgs fmax(lgs x, lgs y) {
	bool ok = 0;
	if (x.len > y.len) ok = 1;
	else if (x.len < y.len) ok = 0;
	else {
		for (int i = x.len; i >= 1; i--) {
			if (x.n[i] > y.n[i]) {
				ok = 1;
				break;
			} else if (x.n[i] < y.n[i]) {
				ok = 0;
				break;
			}
		}
	}
	if (ok) return x;
	else return y;
}
lgs XXH_AK_IOI,TWX_AK_IOI,WJR_NOIP_0;
int main() {
	scanf("%d",&n);
	scanf("%d %d",&gw.l,&gw.r);
	for(int i=1; i<=n; i++)
		scanf("%d %d",&dc[i].l,&dc[i].r);
	sort(dc+1,dc+n+1,cmp);
	XXH_AK_IOI.len=1,XXH_AK_IOI.n[1]=gw.l;
	for(int i=1;i<=n;i++) {
	    div(XXH_AK_IOI,dc[i].r,TWX_AK_IOI);
	    mul(XXH_AK_IOI,dc[i].l,XXH_AK_IOI);
	    WJR_NOIP_0=fmax(TWX_AK_IOI,WJR_NOIP_0);
	}
	write(WJR_NOIP_0);
}

B

題目應該找不到,所以這裡簡述下:

經典 \(01\) 揹包,不過 \(1\le n\le 40\)\(1\le m\le 10^8\)

考慮爆搜,然後過了……

時間複雜度:\(O(2^n)\)

#include<bits/stdc++.h>
using namespace std;
int n,m,ans,x,a[46];
void dfs(int dep,int sum) {
    if(sum>m)
        return;
    if(sum==m) {
        printf("%d\n",sum);
        exit(0);
    }
    if(dep==n+1) {
        ans=max(ans,sum);
        return;
    }
    dfs(dep+1,sum);
    dfs(dep+1,sum+a[dep]);
}
int main() {
   	scanf("%d %d",&n,&m);
   	for(int i=1;i<=n;i++)
   	    scanf("%d",&a[i]);
   	dfs(1,0);
    printf("%d\n",ans);
}

C

求一棵樹中任意一點到其他點的最長距離。

Tree DP+換根。

#include<bits/stdc++.h>
using namespace std;
int n,x,y;
int son[200010],nxt[200010],head[200010],tot;
int dp[100010][2];
void add(int x,int y) {
    son[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
void dfs(int x,int fa) {
    for(int i=head[x];i;i=nxt[i]) 
	    if(son[i]!=fa) {
            dfs(son[i],x);
            int zsd=dp[son[i]][0]+1;
            if(zsd>dp[x][0])
                swap(dp[x][0],zsd);
            if(zsd>dp[x][1])
                swap(dp[x][1],zsd);
        } 
} 
void dfs_(int x,int fa) {
	for(int i=head[x];i;i=nxt[i]) 
	    if(son[i]!=fa) {
	    	int zsd;
	    	if(dp[x][0]==dp[son[i]][0]+1)
	    	    zsd=dp[x][1]+1;
	    	else
	    	    zsd=dp[x][0]+1;
            if(zsd>dp[son[i]][0])
                swap(dp[son[i]][0],zsd);
            if(zsd>dp[son[i]][1])
                swap(dp[son[i]][1],zsd);
            dfs_(son[i],x);
        } 
}
int main() {
    scanf("%d",&n);
	for(int i=1;i<n;i++) {
	    scanf("%d %d",&x,&y);
	    add(x,y);
	    add(y,x);
    }
    dfs(1,0);
    dfs_(1,0);
    for(int i=1;i<=n;i++)
        printf("%d\n",dp[i][0]);
}