A. Drazil and Factorial(516A)
题目链接
http://codeforces.com/contest/516/problem/A
题目大意
定义
F(a)
为数字
a
的每一位数字的阶乘之积,要你找出一个最大的数字
思路
可以找到下面的规律:
0!
(无视掉)
1!
(无视掉)
2!=2!
3!=3!
4!=2!2!3!
5!=5!
6!=5!3!
7!=7!
8!=7!2!2!2!
9!=7!3!3!2!
其中2 3 5 7均未变,显然在同样的F值下,用4 6 8 9不如拆成2 3 5 7来用更划算,因此最终的答案的每一位也显然只会出现2 3 5 7,因此我们可以对原来的 F(a) 分解质因数,然后先尽量用光 7! ,再尽量用光 5! ,依次类推,就可以得到最大的答案了
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
int n,fact[25],t[25];
char s[25];
void cal(int num,int val) //val=1是添加质因数,-1是减少质因数
{
for(int x=2;x*x<=num;x++)
while(num%x==0)
{
num/=x;
t[x]+=val;
}
if(num>1) t[num]+=val;
}
int main()
{
scanf("%d",&n);
fact[1]=1;
for(int i=2;i<=9;i++) fact[i]=fact[i-1]*i;
scanf("%s",s+1);
for(int i=1;i<=n;i++)
cal(fact[s[i]-'0'],1);
while(t[7]) cal(fact[7],-1),printf("7");
while(t[5]) cal(fact[5],-1),printf("5");
while(t[3]) cal(fact[3],-1),printf("3");
while(t[2]) cal(fact[2],-1),printf("2");
printf("\n");
return 0;
}
B. Drazil and Tiles(516B)
题目链接
http://codeforces.com/contest/516/problem/B
题目大意
给一个带有障碍物的 n∗m 大小的棋盘放入若干个 1∗2 大小的瓦片,问是否存在且仅存在一种使得整个棋盘被障碍物和瓦片完全覆盖,瓦片和障碍物、瓦片和瓦片均不重叠的方案,并输出这种方案。
思路
这个题目的做法真的非常有意思,值得学习
首先我们把每个空格当成一个结点,并求出每个空格的度数(相邻的空格个数),然后我们首先将初始时度数为1的点入队,每次从队首取出一个空格
a
,由于这个点一定是度数为1的,因此我们找出那个唯一的与它相邻的空格
若最终的棋盘里仍有空格,那么表明无可行方案或有多种可行方案。
考虑两种不合法情况:
1、无可行方案。那么显然上面的做法无法覆盖掉所有的棋盘。
2、有多种方案。由于每次我们只选取度数为1的点
a
入队,这些点找到的相邻的空格
实际上这个题可以建立如下一个模型:
给定一个无向图,要你对图中所有的边进行黑白染色,使得最终每个点都只连接一条黑边,问是否存在且仅存在一种合法方案。
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <queue>
#define MAXN 2100
using namespace std;
typedef pair<int,int> pr;
char map[MAXN][MAXN];
int outDegree[MAXN][MAXN];
int n,m;
char s[MAXN];
int xx[]={1,-1,0,0},yy[]={0,0,1,-1};
char tag[4][5]={"^v","v^","<>","><"};
queue<pr>q;
bool vis[MAXN][MAXN];
void NotUnique()
{
cout<<"Not unique\n"<<endl;
exit(0);
}
int tot=0;
bool inMap(int x,int y)
{
if(x<1||x>n||y<1||y>m) return false;
if(map[x][y]!='.') return false;
return true;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",map[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(map[i][j]!='.') continue;
for(int dir=0;dir<4;dir++)
{
int newi=i+xx[dir],newj=j+yy[dir];
if(!inMap(newi,newj)) continue;
outDegree[i][j]++;
}
if(outDegree[i][j]==0) NotUnique();
if(outDegree[i][j]==1) q.push(make_pair(i,j));
}
while(!q.empty())
{
bool find=false;
pr now=q.front();
q.pop();
if(map[now.first][now.second]!='.') continue;
for(int dir=0;dir<4;dir++)
{
int newx=now.first+xx[dir],newy=now.second+yy[dir];
if(!inMap(newx,newy)) continue;
map[now.first][now.second]=tag[dir][0];
map[newx][newy]=tag[dir][1];
for(int dir1=0;dir1<4;dir1++)
{
int nextx=newx+xx[dir1],nexty=newy+yy[dir1];
if(inMap(nextx,nexty))
{
outDegree[nextx][nexty]--;
if(outDegree[nextx][nexty]==1)
{
q.push(make_pair(nextx,nexty));
}
}
}
break; //!!!!!!
}
}
bool flag=true;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(map[i][j]=='.')
{
flag=false;
break;
}
if(!flag) NotUnique();
for(int i=1;i<=n;i++)
printf("%s\n",map[i]+1);
return 0;
}
C. Drazil and Park(516C)
题目链接
http://codeforces.com/contest/516/problem/C
题目大意
在一个环形跑道上种着
n
个树,给出每个树的高度以及两个相邻的树之间的距离,定义从树
思路
首先把这个长度为
在这个问题里多了个
h
值,我们可以让
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXN 210000
#define INF 0x3f3f3f3f
using namespace std;
typedef long long int LL;
struct Info
{
LL Lmax,Rmax,sum,maxsum;
}info[MAXN<<2],ans;
int n,m;
LL d[MAXN],h[MAXN];
void pushup(Info &o,Info lc,Info rc,LL len)
{
o.Lmax=max(lc.Lmax,lc.sum+len+rc.Lmax);
o.Rmax=max(rc.Rmax,rc.sum+len+lc.Rmax);
o.sum=lc.sum+len+rc.sum;
o.maxsum=max(max(lc.maxsum,rc.maxsum),lc.Rmax+len+rc.Lmax);
}
void Build(int o,int L,int R)
{
if(L==R)
{
info[o].Lmax=info[o].Rmax=2*h[L];
return;
}
int M=(L+R)>>1;
Build(o<<1,L,M);
Build(o<<1|1,M+1,R);
pushup(info[o],info[o<<1],info[o<<1|1],d[M]);
}
void query(int o,int L,int R,int ql,int qr)
{
if(ql<=L&&R<=qr)
{
if(ql==L) ans=info[o];
else pushup(ans,ans,info[o],d[L-1]);
return;
}
int M=(L+R)>>1;
if(ql<=M) query(o<<1,L,M,ql,qr);
if(qr>M) query(o<<1|1,M+1,R,ql,qr);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%I64d",&d[i]);
d[i+n]=d[i];
}
for(int i=1;i<=n;i++)
{
scanf("%I64d",&h[i]);
h[i+n]=h[i];
}
Build(1,1,n*2);
for(int i=1;i<=m;i++)
{
int x,y,L,R;
scanf("%d%d",&L,&R);
if(L>R)
{
x=R+1;
y=L-1;
}
else
{
x=R+1;
y=n+L-1;
}
query(1,1,2*n,x,y);
printf("%I64d\n",ans.maxsum);
}
return 0;
}