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個,所以:
空間複雜度
時間複雜度
空間卡的比較緊,不要在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
奇怪的做法。我的代碼代碼實在很醜,簡單實現即可。
咕咕咕。