0 粉刷(paint)
鸡腿想到了一个很高(sha)明(bi)的问题,墙可以看作一个N*M的矩阵,有一些格子是有污点的。现在鸡腿可以竖着刷一次,覆盖连续的最多C列,或者横着刷一次,覆盖连续的最多R行。现在鸡腿把墙上的情况告诉你,请你告诉鸡腿最少要刷多少次才能刷干净!
对于50%的数据1≤N,M≤5;
对于100%的数据1≤N,M,R,C≤15。
由于数据只有15,就直接枚举。。。
枚举行的粉刷情况,当行的粉刷情况确定后,列的粉刷次数是不变的,可以直接计算
所以就搜出所有行的粉刷情况,算出分别对应的粉刷次数,更新答案
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,r,c,ans=2000;
int a[20][20];
int h[20],l[20];
void dfs(int k,int s){
if (k>n){
for (int i=1;i<=m;i++)
l[i]=0;
for (int i=1;i<=n;i++)
if (h[i]==0)
for (int j=1;j<=m;j++)
if (a[i][j]==1) l[j]=1;
for (int i=1;i<=m;i++)
if (l[i]){
i=i+c-1;
s++;
}
if (ans>s) ans=s;
return;
}
for (int i=k;i<=n;i++)
if (h[i]==0){
for (int j=i;j<min(i+r,n+1);j++)
h[j]=1;
dfs(i+r,s+1);
for (int j=i;j<min(i+r,n+1);j++)
h[j]=0;
}
dfs(n+1,s);
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
char ch[20];
scanf("%s",ch+1);
for (int j=1;j<=m;j++)
if (ch[j]=='X') a[i][j]=1;
}
scanf("%d%d",&r,&c);
dfs(1,0);
printf("%d",ans);
}
1 运算符(calc)
鸡腿想到了一个很高(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取模就可以了哦!
对于30%的数据0 <n ≤ 10, 0 <k ≤ 10;
对于100%的数据0 <n ≤ 1000, 0 <k ≤ 100。
先考虑求
n
!
k
n!k
n!k的递推式:
f
[
n
]
[
k
]
=
f
[
n
−
1
]
[
k
]
∗
f
[
n
]
[
k
−
1
]
f[n][k]=f[n-1][k]*f[n][k-1]
f[n][k]=f[n−1][k]∗f[n][k−1]
既然是乘法,那么如果我们分别分解
f
[
n
−
1
]
[
k
]
f[n-1][k]
f[n−1][k]和
f
[
n
]
[
k
−
1
]
f[n][k-1]
f[n][k−1]的约数个数,再直接相加,即可得到对于每个
f
[
i
]
[
j
]
f[i][j]
f[i][j]每种不同质因数的个数
设 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]表示 n = i , k = j 时,第k个质因子的数量
最后把 f [ n ] [ k ] [ i ] f[n][k][i] f[n][k][i]+1相乘即可
#include <cstdio>
using namespace std;
const long long mod=1000000009;
int n,k;
long long ans;
int f[1005][105][170];
long long c[1005];
int a[1005],p[1000],b[1005];
void prin(){
for (int i=2;i<=n;i++){
if (b[i]==0) p[++p[0]]=i,c[i]=1;
for (int j=1;i*p[j]<=n&&j<=p[0];j++){
b[i*p[j]]=1;
if (i%p[j]==0) break;
}
}
}
int main(){
scanf("%d%d",&n,&k);
prin();
for (int i=1;i<=n;i++){
int x=i;
for (int j=1;j<=p[0]&&x>1;j++)
if (x%p[j]==0){
while (x%p[j]==0&&x>1){
x/=p[j];
f[i][0][j]++;
}
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=k;j++)
for (int l=1;l<=168;l++)
f[i][j][l]=(f[i-1][j][l]+f[i][j-1][l])%mod;
ans=1;
for (int i=1;i<=p[0];i++)
ans=(long long)(f[n][k][i]+1)*ans%mod;
printf("%lld",ans);
}
2 倾斜的线
有一个很详细的题解,配有高清大图,看了图就懂了!(乱说的)
讲了斜率最大值、坐标变换下的斜率最大值
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
long double k,mi;
long long n,p,q,ans;
struct cv{
long long x,y;
}a[200006];
bool comp(cv a,cv b){
return a.x*p-a.y*q<b.x*p-b.y*q;
}
long long gcd(long long a,long long b){
if (b==0) return a;
return gcd(b,a%b);
}
long long _gcd(long long a,long long b){
if (a<b) swap(a,b);
return gcd(a,b);
}
int main(){
freopen("slope.in","r",stdin);
freopen("slope.out","w",stdout);
scanf("%lld%lld%lld",&n,&p,&q);
k=(long double)p/q;
for (int i=1;i<=n;i++)
scanf("%lld%lld",&a[i].x,&a[i].y);
sort(a+1,a+1+n,comp);
mi=(long double)(a[1].y-a[2].y)/(a[1].x-a[2].x),ans=1;
for (int i=2;i<n;i++){
long double xie=(long double)(a[i].y-a[i+1].y)/(a[i].x-a[i+1].x);
if (fabs(xie-k)<fabs(mi-k)){
mi=xie;
ans=i;
}
}
long long g=_gcd(a[ans].y-a[ans+1].y,a[ans].x-a[ans+1].x);
printf("%lld/%lld",(a[ans].y-a[ans+1].y)/g,(a[ans].x-a[ans+1].x)/g);
}
你对我的虚伪让我的心受到太大的痛苦了,我很难忘记。——摘自贝多芬给侄子的信
=你好虚伪
此名人名言适用于各大表情包