1. 程式人生 > 實用技巧 >10.26 考試總結

10.26 考試總結

\(T2\) 原本能過的,結果特判了 \(k=1\) 的情況,就 \(tm\) 哪裡全錯了。就 \(nm\) 離譜

$ T3$ 打的暴力也不知道哪裡打掛了。

T1 Diy 手工

desprition

H 小姐的生日很快就要到了,小 Z 還在思索應該送 H 小姐什麼生日禮物 才好。送化妝品太貴,送巧克力又太俗

了……突然,小 Z 靈機一動,打算做一 個 diy 手工以顯誠意。 小 Z 找來了好多長度為 N 的冰棒棍,他打算把

這些冰棒棍切割成若干段,然後拼接成一個個長方體,然後再用這些長方體壘成城堡。然而,小 Z 卻開始 為長方

體長寬高的選取而煩惱:設長方體的長寬高分別為 \(L,W,H\),為了更好地 利用這些長度為 \(N\)

的冰棒棍,

小 Z 希望把這些冰棒棍分為四組,其中第一組都 能恰好切割成若干段長(L 整除 N),

第二組切割成若干段寬(W 整除 N),第三 組切割成若干段高(H 整除 N),

最後一組恰好切割成長寬高各(N=L+W+H)。 現在,小 Z 好奇,拼成的長方體,體積最大是多少?

output

每組測試資料輸出一行,包含一個整數,表示長方體的最大體積。若不 存在合法方案,輸出 \(-1\)

對於 100% 的資料範圍 \(T\leq 10^6,n\leq 10^6\)

solution

打表找規律題。

結論:

  • \(n \bmod 3 == 0\) 答案為 \(({n\over 3})^3\)

  • 除此之外當 \(n\bmod 4 == 0\) 答案為 \({n\over2} \times {n\over 4}\times{n\over 4}\)

  • 否則無解

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int T,n;
inline int read()
{
	int s = 0,w = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
	return s * w;
}
int main()
{
	freopen("diy.in","r",stdin);
	freopen("diy.out","w",stdout);
	T = read();
	while(T--)
	{
		n = read();
		if(n % 3 == 0) printf("%lld\n",1LL * (n/3) * (n/3) * (n/3));
		else if(n % 4 == 0) printf("%lld\n",1LL * (n/2) * (n/4) * (n/4));
		else printf("%d\n",-1);
	}
	fclose(stdin); fclose(stdout);
	return 0;
}

T2 tower

Desprition

勇 士 有 \(K\) 個 屬 性 , 大 小 分 別 為 \(v[1],v[2],…,v[K]\),一共有 \(N\) 只怪物,每隻怪物也有相應的 \(K\) 個屬性,

\(i\) 只 怪 物 的 第 \(j\) 項 屬 性 標 記 為 \(a[i][j]\) 。 若 對 於 任 意 的 \(j\)\(1≤j≤K\) ) 都 有 \(a[i][j]≤v[j]\)

則勇士可以幹掉第 \(i\) 只怪物,而且幹掉第 \(i\) 只怪物後,勇士的 各項屬性都會得到提升,

其中第 \(j\) 項屬性的提升了 \(b[i][j]\)。 現在小 Z 好奇,按照最優策略來打怪,最多能幹掉多少隻怪物。

input

第一行為測試資料組數 \(T(1≤T≤10)\)。 每組測試資料的第一行為怪物數 \(N\) 及屬性數 \(K\)

第二行包含 \(K\) 個非負整數分別表示 \(v[1],v[2],…,v[K]\)

接下來 \(N\) 行,第 \(i\) 行包含$ 2\times K$ 個非負整數,表示 \(a[i][1],a[i][2],…a[i][K]\)\(b[i][1],b[i][2],…,b[i][K]\)

具體含義見題面。

output

對於每組測試資料,輸出第一行包含一個整數 \(M\),表示小 Z 最多能幹掉多 少只怪物。

第二行包含 \(K\) 個整數,表示幹掉 \(M\) 只怪物後,勇士的 \(K\) 項屬性分別 是多少

solution

暴力跑的比正解還快,加個快讀就過了 。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e5+10;
int T,n,k,maxn,ans;
int t[N],a[N][6],b[N][6];
bool vis[N];
struct node
{
	int id,w;
}e[N];
inline int read()
{
	int s = 0,w = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
	return s * w;
}
bool comp(node a,node b)
{
	return a.w < b.w;
}
bool judge(int x)
{
	for(int i = 1; i <= k; i++)
	{
		if(t[i] < a[x][i]) return 0;
	}
	return 1;
}
int main()
{
	freopen("tower.in","r",stdin);
	freopen("tower.out","w",stdout);
	T = read();
	while(T--)
	{
		n = read(); k = read(); ans = 0;
		memset(vis,0,sizeof(vis));
		for(int i = 1; i <= k; i++) t[i] = read();
		for(int i = 1; i <= n; i++) 
		{
			int sum = 0;
			for(int j = 1; j <= k; j++)
			{
				a[i][j] = read();
				sum += max(0,a[i][j] - t[j]);
			}
			for(int j = 1; j <= k; j++) b[i][j] = read();
			e[i].id = i; e[i].w = sum;
		}
		sort(e+1,e+n+1,comp);
		while(1)
		{
			int num = 0;
			for(int i = 1; i <= n; i++)
			{
				if(vis[i]) continue;
				else if(judge(e[i].id))
				{
					num++; vis[i] = 1;
					for(int j = 1; j <= k; j++) t[j] += b[e[i].id][j];
				}
			}
			if(num == 0) break;
			ans += num;
		}
		printf("%d\n",ans);
		for(int i = 1; i <= k; i++) printf("%d ",t[i]);
		printf("\n");
	}
	fclose(stdin); fclose(stdout);
	return 0;
}

T3 sport

Desprition

一年一度的趣味運動會馬上就要開始啦!作為班長的小 Z 最近正忙於制定 策略,決定派哪些同學參加哪些

趣味專案。其中最棘手的莫過於二人三足,顧 名思義,這個運動需要每組兩位同學默契配合,才能走得儘可

能的快。 已知全班共有 \(N\) 位同學報名參加趣味運動會,小 Z 需要在這 \(N\) 位同學中選 出若干對同學,

組隊參加二人三足。可惜的是,這 \(N\) 位同學之間總是小摩擦不 斷,說不準昨天 \(A\)\(B\) 吵架了,

不再適合組隊,而沒過多久,前天吵架的 \(C\)\(D\) 就又突然和好了。

小 Z 得知這 \(N\) 位同學的吵架及和好事件的發生,他好奇每 發生一次吵架或和好後,

派出 \(k\) 組同學參加二人三足的方案數,分別是多少。

其中 \(k=1,2,……,N/2\)

input

第一行為測試資料組數 \(T(1≤T≤10)\)。 每組測試資料的第一行為學生數量 \(N\) 及事件數 \(M\) .

其中 \(N\) 為偶數。 接下來 \(M\) 行,第 \(i\) 行通過一個三元組 \(c u v\) 描述一個事件,

其中 \(c\) 為字元, 要麼是“+”要麼是“-”,

\(u\) 和$ v$ 為吵架(用“-”表示)或和好(用“+”表 示)的兩位同學的編號。

資料保證兩位剛和好的同學之前處於吵架狀態,而剛吵架的同學之前處於 和好狀態。

output

每組資料輸出 \(M\) 行,包含 \(N/2\) 個數字,第 \(k\) 個數字表示派出 \(k\) 組同學參賽 的方案數對 \(10^9+7\) 取模後是多少。

\(T\leq 10,n\leq 10,m\leq 3000\)

sloution

狀壓 \(dp\) .

\(f[i][j]\) 表示選的人的集合為 \(i\) ,配對數為 \(j\) 的方案數。

初始化 : \(f[0][0] = 1\)

轉移時列舉每個不選 \(u,v\) 的狀態 \(i\) 進行轉移。

\(tmp = (1<<(u-1)) | (1<<(v-1))\)

\(u,v\) 和好,則 \(f[i\) $or $ $ tmp] $ \([j] += f[i][j-1]\) \(ans[j] += f[i][j-1]\) .

反之 \(f[i\) \(or\) $ tmp][j] -= f[i][j-1]$ \(ans[j] -= f[i][j-1]\)

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int p = 1e9+7;
int T,n,m,u,v,f[100010][6],ans[6];
inline int read()
{
	int s = 0,w = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
	return s * w;
}
int main()
{
	freopen("sport.in","r",stdin);
	freopen("sport.out","w",stdout);
	T = read();
	while(T--)
	{
		memset(f,0,sizeof(f));
		memset(ans,0,sizeof(ans));
		n = read(); m = read();
		f[0][0] = 1;
		for(int Q = 1; Q <= m; Q++)
		{
			char ch = getchar();
			while(ch != '+' && ch != '-') ch = getchar();
			u = read(); v = read();
			if(ch == '+')
			{
				int k = ((1<<n)-1) ^((1<<(u-1)) | (1<<(v-1)));
				int tmp = ((1<<(u-1)) | (1<<(v-1)));
				for(int i = k; ; i = (i-1) & k)//列舉每個不選 u,v的狀態進行轉移
				{
					for(int j = 1; j <= n/2; j++)
					{
						f[i | tmp][j] = (f[i | tmp][j] + f[i][j-1]) % p;
						ans[j] = (ans[j] + f[i][j-1]) % p;
					}
					if(!i) break;
				}
			}
			else
			{
				int k = ((1<<n)-1) ^ ((1<<(u-1)) | (1<<(v-1)));
				int tmp = ((1<<(u-1)) | (1<<(v-1)));
				for(int i = k; ; i = (i-1) & k)
				{
					for(int j = 1; j <= n/2; j++)
					{
						f[i | tmp][j] = (f[i | tmp][j] - f[i][j-1] + p) % p;
						ans[j] = (ans[j] - f[i][j-1] + p) % p;
					}
					if(!i) break;
				}
			}
			for(int i = 1; i <= n/2; i++) printf("%d ",ans[i]);
			printf("\n");
		}
	}
	fclose(stdin); fclose(stdout);
	return 0; 
}