您的位置:首页 > 其它

大二周赛之今天有点不开心(-。-;)

2015-12-12 16:13 218 查看
第一题:来源于POJ3690

题意:给出一个n * m的矩阵,矩阵中只有一些*或者0,n <= 1000, m <= 1000,然后有t (t <= 100)个询问,每次询问给出一个p * q的矩阵,p,q是提前固定的数值,问这些询问中能是大矩阵的子矩阵的有几个。

解法:hash.把每一行连续的p个数hash成一个long long 的二进制数,就可减少判断的次数,当然也可以将每个P* Q的矩阵给hash一个数(要用unsigned,可以自动取模)。

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;

long long h[1111][1111];
int n, m, t, p, q;
char mp[1111][1111], tmp[66];
long long a[66];
bool ok()
{
for(int i=0;i+p-1<n;i++)
for(int j=q-1;j<m;j++)
{
int flag=1;
for(int k=0;k<p;k++)
if(h[i+k][j]!=a[k])
{
flag = 0;
break;
}
if(flag) return true;
}
return false;
}
int main()
{
int cas = 0;
while(scanf("%d%d%d%d%d",&n,&m,&t,&p,&q) != EOF)
{
if(!n && !m && !t && !q && !p) break;
for(int i=0;i<n;i++) scanf("%s",mp[i]);
memset(h,0,sizeof(h));
for(int i=0;i<n;i++)
for(int j=0;j<q;j++)
if(mp[i][j]=='*') h[i][q-1]|=(1LL<<j);
for(int i=0;i<n;i++)
for(int j=q;j<m;j++)
{
if(mp[i][j-q]=='*')      h[i][j]=h[i][j-1]-1LL;
else                     h[i][j]=h[i][j-1];
h[i][j]>>=1LL;
if(mp[i][j]=='*') h[i][j]|=(1LL<<(q-1));
}

int cnt=0;
while(t--)
{
for(int i=0;i<p;i++)
{
scanf("%s",tmp);
a[i]=0;
for(int j=0;j<q;j++)
if(tmp[j]=='*') a[i]|=(1LL << j);
}
if(ok()) cnt++;
}
printf("Case %d: %d\n", ++cas, cnt);
}
return 0;
}


第二题: 来源于:CodeForces 373A

题意:统计所有十六个格子内的数据个数,不超过2*k输出YES

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;

int main()
{
int k;
char b[5];
int a[9];
int max=0;
memset(a,0,9*sizeof(int));
while(~scanf("%d",&k))
{
for(int i=0;i<4;i++)
{
scanf("%d",&k);
for(int j=0;j<4;j++)
{
if(b[j]!='.')
{
a[b[j]-'1']++;
if(a[b[j]-'1']>max)
max=a[b[j]-'1'];
}
}
}
if(max>2*k) puts("NO");
else        puts("YES");
}
return 0;
}


第三题:来源于:CodeForces 373B

题意:从m开始做一个单调序列{m , m+1 , m+2 , …} 每次可以加一个元素 每个元素费用为数字的位数 每个数字费用k 求 不超过w花费可加几个元素。

解法:枚举长度。

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;

#define ll long long
ll ans,m,k,w;
ll dig[20];

int main()
{
int i;
dig[1]=1;
for(i=2;i<=19;i++) dig[i]=dig[i-1]*10;
while(~scanf("%lld%lld%lld",&w,&m,&k))
{
ans=0;
w/=k;
for(i=1;i<=16;i++)
if(dig[i]>m) break;
while(w)
{
if(w>=(dig[i]-m)*(i-1))
{
ans+=dig[i]-m;
w-=(dig[i]-m)*(i-1);
m=dig[i];
}
else
{
ans+=w/(i-1);
w=0;
}
m=dig[i];
i++;
}
printf("%lld\n",ans);
}
return 0;
}


第四题:来源于CodeForces 375A

题意:一堆数字一定包含1、6、8、9 可以任意调整顺序 最后排成的数字要求被7整除

解法:找规律。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

char num[1000010];
int flag[10];

int main()
{
int i,len,tmp;
while(~scanf("%s",num))
{
len=strlen(num);
memset(flag,0,sizeof(flag));
tmp=0;
for(i=0;i<len;i++)
{
if(num[i]=='0') flag[0]++;
else if(num[i]=='1'&&!flag[1]) flag[1]=1;
else if(num[i]=='6'&&!flag[6]) flag[6]=1;
else if(num[i]=='8'&&!flag[8]) flag[8]=1;
else if(num[i]=='9'&&!flag[9]) flag[9]=1;
else
{
printf("%c",num[i]);
tmp=tmp*10+num[i]-'0';
tmp%=7;
}
}
if(tmp==0) printf("1869");
else if(tmp==1) printf("6198");
else if(tmp==2) printf("1896");
else if(tmp==3) printf("6918");
else if(tmp==4) printf("1986");
else if(tmp==5) printf("1968");
else if(tmp==6) printf("1698");
for(i=1;i<=flag[0];i++) printf("0");
printf("\n");
}
return 0;
}


第五题:来源于:HDU203

题意:略

解法:题目要求的是至少收到一份Offer的最大概率,我们得到得不到的最小概率即可,状态转移方程:f[j]=min(f[j],f[j-v[i]]*w[i]);其中,w[i]表示得不到的概率,(1-f[j])为花费j元得到Offer的最大概率

代码:略:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: