jz集訓 8.17

Day 17

85

T1

Description

雞腿想到了一個很高(sha)明(bi)的問題,牆可以看作一個N*M的矩陣,有一些格子是有污點的。現在雞腿可以豎着刷一次,覆蓋連續的最多C列,或者橫着刷一次,覆蓋連續的最多R行。現在雞腿把牆上的情況告訴你,請你告訴雞腿最少要刷多少次才能刷乾淨!

Input

第1行,輸入倆正整數N,M。

第2到N+1行,每行一個長度爲M的字符串,每個字符可能是’.’表示乾淨的,或者’X’表示這個格子有污點。

第N+2行,輸入倆正整數表示R和C。

Output

輸出一行一個整數,表示雞腿最少要刷幾次。

Sample Input

輸入1:

1 9

XXXXXXXXX

2 3

輸入2:

11 14

XXX…XXX…XXX.

.X…X…X…X

.X…X…X…X

.X…X…X…X

.X…XXX…XXX.

…XX…XXX…

…X…X…

…X…XXX…

…X…X…

…XXX…XXX…

1 2

Sample Output
輸出1:

1

輸出2:

7

Data Constraint

對於50%的數據1≤N,M≤5;

對於100%的數據1≤N,M,R,C≤15。

Solution

80pts
對於每個髒點,枚舉是橫着清除還是豎着清除,dfs即可。

100pts
枚舉橫着清除哪些橫行,再處理豎列,統計答案。

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef pair<int, int> p;
const int N = 16;
const int INF = 0x3f3f3f3f;
int n,m,r,c,ans=INF;
bool a[N][N];
bool dox[N],doy[N];
char read(){
	char ch=getchar();
	while(ch!='.' && ch!='X'){
		ch=getchar();
	}
	return ch;
}
int cal(){
	int res=0;
	bool flag=0;
	int last=0,left=c;
	for(int i=1; i<=m; i++){
		if(doy[i]==1){
			if(!flag){
				flag=1;
				res++;
				last=i;
				left--;
			}
			else{
				if(last==i-1){
					if(left==0){
						left=c-1;
						res++;
					}
					else{
						left--;
					}
					last++;
				}
				else{
					res++;
					left=c-1;
					last=i;
				}
			}
		}
	}
	return res;
}
int work(int sta){
	memset(dox, 0, sizeof dox);
	memset(doy, 0, sizeof doy);
	int res=0;
	bool flag=0;
	int last=0,left=r;
	for(int i=1; i<=n; i++){
		if(((sta>>(i-1)) & 1)==1){
			dox[i]=1;
			if(!flag){
				flag=1;
				res++;
				last=i;
				left--;
			}
			else{
				if(last==i-1){
					if(left==0){
						left=r-1;
						res++;
					}
					else{
						left--;
					}
					last++;
				}
				else{
					res++;
					left=r-1;
					last=i;
				}
			}
		}
	}
	flag=0;
	last=0;
	left=c;
	for(int i=1; i<=n; i++){
		if(!dox[i]){
			for(int j=1; j<=m; j++){
				if(!doy[j] && !a[i][j]){
					doy[j]=1;
				}
			}
		}
	}
	res+=cal();
	return res;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++){
		for(int j=1; j<=m; j++){
			char ch=read();
			if(ch=='.'){
				a[i][j]=1;
			}
			else if(ch=='X'){
				a[i][j]=0;
			}
		}
	}
	scanf("%d%d",&r,&c);
	for(int i=0; i<(1<<n); i++){
		ans=min(ans, work(i));
	}
	printf("%d\n",ans);
	return 0;
}

T2

Description

雞腿想到了一個很高(sha)明(bi)的運算符,那就是’!’,沒錯就是感嘆號。他給瞭如下的定義:

1、n!k = n!(k-1) * (n-1)!k (n> 0 and k > 0)

2、n!k = 1 (n = 0)

3、n!k = n (k = 0)

現在雞腿告訴你n和k你能告訴他n!k的不同約數個數有多少個嗎?只要對1,000,000,009取模就可以了哦!

Input

一行,輸入兩個正整數n,k。

Output

一行,輸出一個整數表示答案。

Sample Input

輸入1:

3 1

輸入2:

100 2

Sample Output

輸出1:

4

輸出2:

321266186

Data Constraint

對於30%的數據0 <n ≤ 10, 0 <k ≤ 10;

對於100%的數據0 <n ≤ 1000, 0 <k ≤ 100。

Solution

令f[i][j][x]表示n=i,k=j時第x個質數有幾個。
初值:f[i][0][x]=i分解質因數後第x個質數的個數。
轉移:f[i][j][x]=(f[i-1][j][x]+f[i][j-1][x])%mod

1000以內的質數有168個,所以:
空間複雜度O(168×NK)O(168\times NK)
時間複雜度O(168×NK)O(168\times NK)

空間卡的比較緊,不要在f上開long long,ans上開即可。

#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1010;
const int K = 110;
const int P = 170;
const int mod = 1000000009;
int n,k,pri[N],cntp;
long long ans=1;
bool vis[N];
int f[N][K][P];
void init(){
	for(int i=2; i<=n; i++){
		if(!vis[i]){
			pri[++cntp]=i;
			for(int j=1; j<=n/i; j++){
				vis[i*j]=1;
			}
		}
	}
}
int main(){
	scanf("%d%d",&n,&k);
	init();
	for(int i=1; i<=n; i++){
		int x=i;
		for(int j=1; j<=cntp; j++){
			while(x%pri[j]==0 && x>0){
				f[i][0][j]++;
				x/=pri[j];
			}
		}
	}
	for(int i=1; i<=n; i++){
		for(int j=1; j<=k; j++){
			for(int p=1; p<=cntp; p++){
				f[i][j][p]=(f[i-1][j][p]+f[i][j-1][p])%mod;
			}
		}
	}
	for(int i=1; i<=cntp; i++){
		ans=(ans*(long long)(f[n][k][i]+1))%mod;
	}
	printf("%lld\n",ans);
	return 0;
}

T3

Description

在這裏插入圖片描述

Solution

在這裏插入圖片描述

奇怪的做法。我的代碼代碼實在很醜,簡單實現即可。
咕咕咕。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章