Codeforces Round #355 (Div. 2)
说实在话,CF手快不及眼快,我题目意思还没读懂别人都写完了…冲1800的希望又破灭了…
A. Vanya and Fence
大于h就是2,小于等于就是2,一个个加起来。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,h,a[1005],ans;
int main()
{
scanf("%d%d",&n,&h);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++) if (a[i]>h) ans+=2;
else ans++;
printf("%d\n",ans);
return 0;
}
B. Vanya and Food Processor
这一题按照题目意思模拟就行了,注意结果要用long long。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,h,a[100005],k;
long long ans;
int main()
{
scanf("%d%d%d",&n,&h,&k);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
int p=0,i=1,q;
ans=0;
while(i<=n)
{
while(p+a[i]<=h)
{
p+=a[i];
i++;
}
q=(a[i]+p-h+k-1)/k;
p=p-q*k;
if (p<0) p=0;
ans+=q;
}
ans+=(p+k-1)/k;
printf("%I64d\n",ans);
return 0;
}
C. Vanya and Label
这题题目我就读了好半天…
大致意思是有一个长度为n的串,因为每个字母都有一个值,如果两个串每一位的值都相同,我们就认为这两个串是相等的,现在让你求有多少组串:每组串按位且后与当前串相等。
对于这题我们考虑按位处理,因为是且,所以我们只能在0上处理,对于每个0有三种情况(0,0)(0,1)(1,0),所以我们处理出每一位上的0有多少个在乘进结果就行了。
答案同样是long long.
#include <iostream>
#include <cstring>
#include <cstdio>
#define mod 1000000007
using namespace std;
char s[100005];
int cos[7]={1,3,9,27,81,243,729};
int main()
{
scanf("%s",s);
int l=strlen(s),num=0;
long long ans=1;
for (int i=0;i<l;i++)
{
int cnt=0;
if (s[i]=='-') num=62;
else if (s[i]=='_') num=63;
else if (s[i]>='0' && s[i]<='9') num=s[i]-'0';
else if (s[i]>='A' && s[i]<='Z') num=s[i]-'A'+10;
else num=s[i]-'a'+36;
for (int j=0;j<6;j++) if ((num&(1<<j))==0) cnt++;
ans=(ans*cos[cnt])%mod;
}
printf("%d\n",ans);
return 0;
}
读题读了这么久写完就这么点….
D. Vanya and Treasure
这一题是说给你一个矩阵,里面有1,2….p,现在你一开始在(1,1)要你找到一条最短的路径从1,2…一直走到p。
大概画出来就是一个明显的层次图,可以想到找到所有的i点,在找到所有的i+1,从i点推i+1。
不过这种方法会超时,因为在枚举i和i+1的时候,个数的乘积可能会很大,所以,当这个乘积很大时我们不如直接对全图做一次SPFA,再把当前的解更新。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <queue>
using namespace std;
struct node
{
int x,y;
node(int x1,int y1):x(x1),y(y1){}
};
int way[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int n,m,p,a[305][305],d[305][305],dis[305][305];
bool flag[305][305];
vector<node> vec[90005];
int main()
{
memset(d,0x3f,sizeof(d));
int high=0;
scanf("%d%d%d",&n,&m,&p);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
vec[a[i][j]].push_back(node(i,j));
}
for (int i=0;i<vec[1].size();i++)
{
int x=vec[1][i].x,y=vec[1][i].y;
d[x][y]=x+y-2;
}
for (int i=2;i<=p;i++)
{
if (vec[i].size()*vec[i-1].size()<n*m)
{
for (int j=0;j<vec[i].size();j++)
{
int x1=vec[i][j].x,y1=vec[i][j].y;
for (int k=0;k<vec[i-1].size();k++)
{
int x2=vec[i-1][k].x,y2=vec[i-1][k].y;
d[x1][y1]=min(d[x1][y1],d[x2][y2]+abs(x1-x2)+abs(y1-y2));
}
}
}
else
{
queue<node> Q;
while(!Q.empty()) Q.pop();
memset(dis,0x3f,sizeof(dis));
memset(flag,0,sizeof(flag));
for (int j=0;j<vec[i-1].size();j++)
{
dis[vec[i-1][j].x][vec[i-1][j].y]=d[vec[i-1][j].x][vec[i-1][j].y];
Q.push(vec[i-1][j]);
flag[vec[i-1][j].x][vec[i-1][j].y]=1;
}
while(!Q.empty())
{
node t=Q.front();
Q.pop();
flag[t.x][t.y]=0;
for (int k=0;k<4;k++)
{
int x=t.x+way[k][0],y=way[k][1]+t.y;
if (x>=1 && x<=n && y>=1 && y<=m && dis[t.x][t.y]+1<dis[x][y])
{
dis[x][y]=dis[t.x][t.y]+1;
if (!flag[x][y])
{
Q.push(node(x,y));
flag[x][y]=1;
}
}
}
}
for (int j=1;j<=n;j++)
for (int k=1;k<=m;k++) if (a[j][k]==i) d[j][k]=dis[j][k];
}
}
int ans=0x7fffffff;
for (int i=0;i<vec[p].size();i++)
{
int x=vec[p][i].x,y=vec[p][i].y;
ans=min(ans,d[x][y]);
}
printf("%d\n",ans);
return 0;
}
这一题的复杂度我不是很懂,题解上给出的复杂度是
O(nmnm−−−√)
,感觉无法理解….
这一题还有不少人使用2维线段树写的,个人感觉与这个迷之复杂度的程序相比,用2维线段树的做法要清晰的多。