问题 G: CD签收
题目描述
在Q迷的千呼万唤之下,N+Q终于推出了新专辑《My Cow Life》.其中一首《God is a cow》更是天籁之音,令Q迷们为之倾倒。可是,让Q迷们不爽的是,这张专辑是限量发行的,并且价格…….许多Q迷们在音像店前排起了长队,想要买到一张CD或者磁带。SGaPb小店的店长SGaPb是个热心人。他看到这么多Q迷想要买专辑,就设计了一个小游戏——抽奖。
规则是这样的:每位Q迷可以抽到一张奖券。奖券上写有1到M这M个自然数。Q迷可以在这M个数中任意选取N个不同的数打圈。每个Q迷只能买一张奖券,不同的奖券上的选择不同。每次抽奖将抽出两个自然数X和Y。如果某人拿到的奖券上,所选N个自然数的倒数和,恰好等于X/Y,则他将免费获得一张CD《My Cow Life》。 现在,已知抽奖结果X和Y。作为N+Q的fans,你的任务是:求出必须准备多少CD,才能保证支付所有获奖者。且对于同一种选数, SGaPb只用支付一盘CD。
输入
输入有且仅有一行,就是用空格分开的四个整数N,M,X,Y。
输出
输出有且仅有一行,即所需准备的CD数量。
样例输入 Copy
2 4 3 4
样例输出 Copy
1
提示
对于30%的数据,1<=N<=M<=15
对于60%的数据,1<=N<=M<=20
对于100%的数据,1<=N<=M<=25,X<=25,Y<=25
暴力模拟
#pragma GCC optimize(2)
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int p=1e9+7;
int n,m,x,y,temp,a[100],b[100],ans;
inline int gcd(register int x,register int y)
{
if(y==0)
return x;
else
return gcd(y,x%y);
}
inline int fun(register int k,register int j,register double sum)
{
if(sum>x*1.0/y+0.1)
return 0;
if(k==n+1)
{
int w1=1,w2=b[1];
for(int i=2;i<=n;i++)
{
int w3=b[i]*w2/gcd(b[i],w2);
w1=w1*w3/w2+w3/b[i];
w2=w3;
}
int w3=gcd(w1,w2);
w1=w1/w3;
w2=w2/w3;
if(w1==x&&w2==y)
{
ans++;
}
return 0;
}
for(register int i=j; i<=m; i++)
{
if(!a[i])
{
a[i]=1;
b[k]=i;
k++;
j=i;
sum+=1.0/i;
fun(k,j,sum);
sum-=1.0/i;
k--;
b[k]=0;
a[i]=0;
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
cin>>n>>m>>x>>y;
temp=gcd(x,y);
x=x/temp;
y=y/temp;
fun(1,1,0);
cout<<ans<<endl;
return 0;
}
问题 D: 显示图像
题目描述
古老的显示屏是由N×M个象素(Pixel)点组成的。一个象素点的位置是根据所在行数和列数决定的。例如P(2,1)表示第2行第1列的象素点。那时候,屏幕只能显示黑与白两种颜色,人们用二进制0和1来表示。0表示黑色,1表示白色。当计算机发出一个指令:P(x,y)=1,则屏幕上的第x行第y列的阴极射线管就开始工作,使该象素点显示白色,若P(x,y)=0,则对应位置的阴极射线管不工作,象素点保持黑色。在某一单位时刻,计算机以N×M二维01矩阵的方式发出显示整个屏幕图像的命令。
例如,屏幕是由3×4象素点组成,在某单位时刻,计算机发出如下命令:
0001
0011
0110
则屏幕图像为:
(假设放大后,一个格子表示一个象素点)
由于未知的原因,显示黑色的象素点总是受显示白色的象素点的影响——可能是阴极射线管工作的作用。并且,距离越近,影响越大。这里的距离定义如下:设有象素点P1(x1,y1)和象素点P2(x2,y2),则它们之间的距离D(P1,P2):D(P1,P2)=|x1-x2|+|y1-y2|
在某一时刻,计算机发出显示命令后,科学家们期望知道,每个象素点和其最近的显示白色的象素点之间的最短距离是多少——科学家们保证屏幕上至少有一个显示白色的象素点。
上面的例子中,象素P(1,1)与最近的白色象素点之间的距离为3,而象素P(3,2)本身显示白色,所以最短距离为0。
输入
第一行有两个数字,N和M (1<=N,M<=1000),表示屏幕的规格。
以下N行,每行M个数字,0或1。为计算机发出的显示命令。
输出
输出有N行,每行M个数字,中间用1个空格分开。第i行第j列的数字表示距象素点P(i,j)最近的白色象素点的最短距离。
样例输入 Copy
3 4
0001
0011
0110
样例输出 Copy
3 2 1 0
2 1 0 0
1 0 0 1
提示
对于100%的数据:N*M<=182^2。
#include <bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int N=182*182;
char str[N+5];
int main()
{
int m,n;
scanf("%d%d",&m,&n);
int a[m+5][n+5]= {0};
int b[m+5][n+5];
memset(b,0x3f3f3f,sizeof(b));
for(int i=1; i<=m; i++)
{
scanf("%s",str);
for(int j=1; j<=n; j++)
{
a[i][j]=str[j-1]-'0';
if(a[i][j]==1)
b[i][j]=0;
}
}
for(int i=m; i>=1; i--)
{
for(int j=1; j<=n; j++)
{
b[i][j]=min(b[i-1][j]+1,b[i][j]);
b[i][j]=min(b[i][j-1]+1,b[i][j]);
b[i][j]=min(b[i+1][j]+1,b[i][j]);
b[i][j]=min(b[i][j+1]+1,b[i][j]);
}
for(int j=n; j>=1; j--)
{
b[i][j]=min(b[i-1][j]+1,b[i][j]);
b[i][j]=min(b[i][j-1]+1,b[i][j]);
b[i][j]=min(b[i+1][j]+1,b[i][j]);
b[i][j]=min(b[i][j+1]+1,b[i][j]);
}
for(int j=1; j<=n; j++)
{
b[i][j]=min(b[i-1][j]+1,b[i][j]);
b[i][j]=min(b[i][j-1]+1,b[i][j]);
b[i][j]=min(b[i+1][j]+1,b[i][j]);
b[i][j]=min(b[i][j+1]+1,b[i][j]);
}
}
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
b[i][j]=min(b[i-1][j]+1,b[i][j]);
b[i][j]=min(b[i][j-1]+1,b[i][j]);
b[i][j]=min(b[i+1][j]+1,b[i][j]);
b[i][j]=min(b[i][j+1]+1,b[i][j]);
}
for(int j=n; j>=1; j--)
{
b[i][j]=min(b[i-1][j]+1,b[i][j]);
b[i][j]=min(b[i][j-1]+1,b[i][j]);
b[i][j]=min(b[i+1][j]+1,b[i][j]);
b[i][j]=min(b[i][j+1]+1,b[i][j]);
}
for(int j=1; j<=n; j++)
{
b[i][j]=min(b[i-1][j]+1,b[i][j]);
b[i][j]=min(b[i][j-1]+1,b[i][j]);
b[i][j]=min(b[i+1][j]+1,b[i][j]);
b[i][j]=min(b[i][j+1]+1,b[i][j]);
}
}
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
printf("%d",b[i][j]);
if(j<n) printf(" ");
}
if(i<m)
printf("\n");
}
return 0;
}
/**************************************************************
Problem: 15428
User: 2019UPC110
Language: C++
Result: 正确
Time:15 ms
Memory:2212 kb
****************************************************************/