#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int a[20][20];
int main()
{
int n;
int ans=1;
cin>>n;
for(int i=0;i<n;i++) a[0][i]=1;
for(int i=0;i<n;i++) a[i][0]=1;
for(int i=1;i<n;i++)
for(int j=1;j<n;j++){
a[i][j]=a[i-1][j]+a[i][j-1];
ans=max(ans,a[i][j]);
}
printf("%d\n",ans);
return 0;
}
B. Painting Pebbles
有n堆个石头,c种颜色,第i堆石头有ai个,能否给全部石头涂色并使得任意两堆石头中涂某种颜色的石头个数的差不大于1。
贪心 ,考虑最大堆和最小堆的石头,两者之差就是多出来的石头,如果多出来的石头数量大于颜色的种类数,根据鸽巢原理,某种颜色一定会出现两次,则不符合。如果可以实现,将颜色和石头编号,然后石头编号对应颜色编号就可以输出一种方案。
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int ans[105][105],a[105];
bool judge(int a,int b,int k){
int tmp;
tmp=(a-b)/k;
if((a-b)%k) tmp++;
if(tmp>1) return false;
return true;
}
int main()
{
int n,k;
int maxx,minn;
maxx=-1;
minn=200;
cin>>n>>k;
for(int i=0;i<105;i++){
for(int j=0;j<105;j++){
ans[i][j]=j%k+1;
}
}
for(int i=0;i<n;i++) {
cin>>a[i];
maxx=max(maxx,a[i]);
minn=min(minn,a[i]);
}
if(judge(maxx,minn,k)){
printf("YES\n");
for(int i=0;i<n;i++){
for(int j=0;j<a[i];j++){
printf("%d",ans[i][j]);
if(j==a[i]-1) printf("\n");
else printf(" ");
}
}
}
else printf("NO\n");
return 0;
}
C. Sums of Digits
题目大意就是a这个序列是一个递增序列,bi是ai的十进制每一位数字之和,给序列bi,求ai,并且an为最小。
贪心+构造,将bi从低位到高位进行分配能使ai最小,但是还要满足a为递增,那么就分两种情况,一种是bi>bi-1,只需要对上一个ai从低位到高位加上bi-bi-1即可(如果某位为9则该位不可加,否则总数就不对了),另外一种情况是bi<=bi-1,这时候就要找到(bi)-1能够构造的最小的大于ai-1的数字,也就是希望ai和ai-1有尽量长的前缀(满足递增的情况下),方法就统计高位的和,到和即将大于或等于bi之前,这时候对高位+1(为了满足递增),低位再按从低到高分配,注意细节即可。
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
char dp[305][400];
int in[305];
int main()
{
int n;
cin>>n;
memset(dp,'0',sizeof(dp));
for(int i=0;i<n;i++){
scanf("%d",&in[i]);
}
int c,cou,tmp;
cou=0;
tmp=in[0];
while(1){
if(tmp<=9){
dp[0][cou++]=tmp+'0';
dp[0][cou]=0;
break;
}
else{
dp[0][cou++]='9';
tmp-=9;
}
}
int len;
for(int i=1;i<n;i++){
if(in[i]>in[i-1]){
tmp = in[i] - in[i-1];
len=strlen(dp[i-1]);
for(int j=0;j<len;j++){
if(tmp==0){
dp[i][j]=dp[i-1][j];
continue;
}
if(dp[i-1][j]<'9'){
if(tmp>'9'-dp[i-1][j]){
dp[i][j]='9';
tmp-='9'-dp[i-1][j];
}
else{
dp[i][j]=dp[i-1][j]+tmp;
tmp = 0;
}
}
else{
dp[i][j] = '9';
}
}
while(tmp){
if(tmp<=9){
dp[i][len++]='0'+tmp;
break;
}
else{
dp[i][len++]='9';
tmp-=9;
}
}
dp[i][len]=0;
}//if(in[i]>in[i-1])
else{
cou = 0;
len = strlen(dp[i-1]);
int j;
for(j = len - 1; j>=0; j--){
if(cou+dp[i-1][j]-'0'<in[i]){
cou+=dp[i-1][j]-'0';
dp[i][j]=dp[i-1][j];
}
else{
break;
}
}
int flag;
for(j=j+1;j<=len;j++){
if(dp[i-1][j]==0){
dp[i][j]='1';
flag = j-1;
len++;
break;
}
if(dp[i-1][j]!='9'){
dp[i][j]=dp[i-1][j]+1;
flag = j-1;
break;
}
}
dp[i][len]=0;
cou = 0;
for(j = flag+1;j<len;j++) cou+=dp[i][j]-'0';
tmp = in[i] - cou;
cou=0;
while(1){
if(tmp<=9){
dp[i][cou++]=tmp+'0';
tmp=0;
break;
}
else{
dp[i][cou++]='9';
tmp-=9;
}
}
for(j = cou;j <= flag;j++){
dp[i][j]='0';
}
}
}
for(int i = 0;i<n;i++){
len = strlen(dp[i]);
for(int j=len-1;j>=0;j--){
printf("%c",dp[i][j]);
}
if(i!=n-1) printf("\n");
}
return 0;
}
E. Pretty Song
按子串的长度为一类进行求和,求和有一个小技巧,将o(n^2)变成线性的复杂度。
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define N 500005
#define LL long long
char txt[N];
double save[N],tmp[N];
bool judge(char a){
if(a=='I') return true;
if(a=='E') return true;
if(a=='A') return true;
if(a=='O') return true;
if(a=='U') return true;
if(a=='Y') return true;
else return false;
}
int main()
{
cin>>txt;
int len;
double ans;
len=strlen(txt);
if(judge(txt[0])) save[0]=1;
for(int i=1;i<len;i++){
save[i]=save[i-1];
if(judge(txt[i])) save[i]++;
}
tmp[0]=save[len-1];
for(int i=1;i<len;i++){
tmp[i]=tmp[i-1]+(save[len-i-1]-save[i-1]);
}
ans=0;
for(int i=0;i<len;i++){
ans+=tmp[i]/(double)(i+1);
}
printf("%.7lf\n",ans);
return 0;
}
F. Progress Monitoring
树形dp,将节点分为某个结点的第一个子树和其他子树,然后用乘法原理计算。
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define N 505
#define LL long long
const int Mod = 1e9+7;
LL dp[N][N];
int in[N];
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>in[i];
}
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++){
dp[i][i]=1;//长度为1的只有一种树结构
}
for(int i=n-2;i>=0;i--){
for(int j = i+1;j<n;j++){
dp[i][j] = dp[i + 1][j];//只有一棵子树的时候
for(int k=i+1;k<=j;k++){
if(in[i+1]<in[k]){
dp[i][j]=(dp[i][j]+dp[i+1][k-1]*dp[k-1][j])%Mod;
}
}
}
}
printf("%I64d\n",dp[0][n-1]);
return 0;
}