链接https://vjudge.net/contest/292686#overview
A. 单词对齐
思路:用stringstream存储所有单词后,再用一个int数组存储每一个位置单词的最大数量以及用一个vector存储单词。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<vector>
using namespace std;
int wsize[205];
vector<string> words[1005];
int main(){
string s;
int len,num = 0,numword;
memset(wsize,0,sizeof(wsize));
while(getline(cin,s)){
stringstream ss(s);
string temp;
numword = 0;
while(ss>>temp){
len = temp.size();
wsize[numword] = max(wsize[numword],len);
words[num].push_back(temp);
++numword;
}
++num;
}
for(int i = 0;i<num;++i){
for(int j = 0;j<words[i].size();++j){
cout<<words[i][j];
int s = (int)words[i][j].size();
if(j != (words[i].size()) - 1){
for(int o = s;o<wsize[j];++o)
cout<<" ";
cout<<" ";
}
}
cout<<endl;
}
return 0;
}
E (区间dp)
题意
给定n个救援人员的坐标与m个避难所的坐标,每个救援人员必须去一个避难所且每个避难所最少要有一名救援人员,求所有救援人员到达避难所的最短路程
dp[n][m]代表前n名人员到达前m和避难所的最短距离,vis[n][m] = 1时,第n-1为成员选择第m个避难所,不然选择第m-1个避难所。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
struct node{
int id;
int t;
long long x;
friend bool operator<(const node &a,const node &b){
return a.x<b.x;
}
};
node a[4005],b[4005];
long long vis[4005][4005],dp[4005][4005] = {0};
bool cmp(node a,node b){
return a.id<b.id;
};
void solve(int n,int m){
if(n == 1&&m == 1){
a[n].t = b[m].id;
return;
}
solve(n-1,m-1+vis[n][m]);
a[n].t = b[m].id;
}
int main(){
int n,m;
while(cin>>n){
for(int i = 1;i<=n;++i){
cin>>a[i].x;
a[i].id = i;
}
sort(a+1,a+1+n);
cin>>m;
for(int i = 1;i<=m;++i){
cin>>b[i].x;
b[i].id = i;
}
sort(b+1,b+1+m);
for(int i = 1;i<=n;++i){
for(int j = 1;j<=m&&j <= i;++j){
if(j == 1){
dp[i][j] = dp[i-1][j] + abs(a[i].x-b[j].x);
vis[i][j] = 1;
}
else if(i == j){
dp[i][j] = dp[i-1][j-1] + abs(a[i].x-b[j].x);
vis[i][j] = 0;
}
else{
dp[i][j] = min(dp[i-1][j-1],dp[i-1][j]) + abs(a[i].x-b[j].x);
if(dp[i-1][j-1] > dp[i-1][j]) vis[i][j] = 1;
else vis[i][j] = 0;
}
}
}
cout<<dp[n][m]<<endl;
solve(n,m);
sort(a+1,a+1+n,cmp);
int ok = 0;
for(int i = 1;i<=n;++i){
if(ok == 0)
ok = 1;
else
cout<<" ";
cout<<a[i].t;
}
cout<<endl;
}
return 0;
}
F
题意:给出n个数p1,p1..pn与m个数q1,q2..qn,求出p1! * p2!....*pn!/(q1!*q2!*..qn!),并以t1!*t2!...*tn*t的形式输出
因为每一个数可以分解为质数的幂的乘积,所以先将阶乘换算为质数的幂的乘积并存储每个质数的个数,然后用而分的方法从大到小的找出t
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
#define MAXN 10010
bool prime[MAXN+5];
int p[1400];
int up;
int num[1400];
int ans[MAXN][2];
vector <short> init[MAXN+2];
void Prime()
{
int i,k;
up=0;
memset(prime,0,sizeof(prime));
for (i=2;i<MAXN;i++)
{
if (prime[i]==1) continue;
k=i;
while(k*i<MAXN)
{
prime[i*k]=1;
k++;
}
p[up++]=i;
}
}
int GetNum(int t,int k)
{
if (t<k) return 0;
return t/k+GetNum(t/k,k);
}
void Init()
{
int i,j;
for (i=1;i<MAXN;i++)
{
for (j=0;j<up;j++)
{
if (i<p[j]) break;
init[i].push_back(GetNum(i,p[j]));
}
}
}
bool Check(int t,int k)
{
int i;
for (i=0;i<k;i++)
{
if (t<p[i]) break;
if (init[t][i]>num[i]) return false;
}
return true;
}
int Count(int t,int &k)
{
int i,ss,tag;
ss=100000;
for (i=0;i<k;i++)
{
if (t<p[i]) break;
ss=min(ss,num[i]/init[t][i]);
}
tag=k;
for (i=0;i<k;i++)
{
if (t<p[i]) break;
num[i]-=ss*init[t][i];
if (num[i]==0) tag=min(tag,i);
}
k=tag;
return ss;
}
int main()
{
int i,j,n,m,s,k,l,r,mid,now,x;
Prime(); //找质数
Init(); //分解质数
while(~scanf("%d%d",&n,&m)){
memset(num,0,sizeof(num));
s=0;
for (i=0;i<n;i++)
{
scanf("%d",&x);
for (j=0;j<up;j++)
{
if (x<p[j]) break;
num[j]+=init[x][j];
}
s=max(s,j);
}
for (i=0;i<m;i++)
{
scanf("%d",&x);
for (j=0;j<up;j++)
{
if (x<p[j]) break;
num[j]-=init[x][j];
}
s=max(s,j);
}
k=s;
for (i=0;i<s;i++)
{
if (num[i]<0) break;
if (num[i]==0) k=min(k,i);
}
if (i<s)
{
printf("-1\n");
continue;
}
now=0;
while(1)
{
if (k==0) break;
l=1;
r=p[k]-1;
while(l<=r)
{
mid=(l+r)/2;
if (Check(mid,k)==true) l=mid+1;
else r=mid-1;
}
ans[now][0]=r;
ans[now++][1]=Count(r,k);
}
printf("%d\n",now);
for (i=0;i<now;i++)
{
printf("%d %d\n",ans[i][0],ans[i][1]);
}
}
return 0;
}