10.27 雅礼考试题

T1 链接 http://lk.yali.edu.cn/contest/3/problem/13

Description

定义函数 f(x)为组成 x 的各位数字之和,如 f(2018)=2+0+1+8=11 .
给定一个正整数 n 求所有满足条件 f(x)+x=n 的 x .

Input

共一行,一个正整数 n。

Output

第一行一个整数 ans 表示有多少个整数 x 满足条件。
下接 ans 行,每行一个整数表示满足条件的 x 。
x按从小到大的顺序输出。

Samples

http://lk.yali.edu.cn/download.php?type=problem&id=13

Constraints

对于 30%的数据满足 : n≤1000
对于 100%的数据满足 : n≤10^18
Time limit : 1s
Memory limit : 512MB

题目分析

乍一看本题,好像并没有什么性质,貌似只能拿一个30的部分分就可以走人了。我们再来看看,题目中有一个定义f(x)+x=n,f(x)为组成 x 的各位数字之和。这说明什么?第一:x一定比n要小;第二f(x)最大为17×9,所以如果x比n小17×9或者更多,那么我们就不能得到答案了。因为n的范围。所以我们可以所后往前枚举,则每次枚举不超过17×9就可一得到答案。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
long long n,a[100];
int cnt;
int main() {
	scanf("%lld",&n);
	if(n<=1e6) {//写if判断主要是怕后面的出错,如果出错了至少还可以得30分QWQ
		for(register int i=1;i<=n;++i) {
			int tt=i,sum=0;
			while(tt) { sum+=tt%10; tt/=10; }
			if(sum+i==n) a[++cnt]=i;
		}
		if(!cnt) {cout<<cnt<<endl;return 0;}
		cout<<cnt<<endl;
		for(register int i=1;i<=cnt;++i) cout<<a[i]<<endl;
	}
	else {
		int nn=0;long long tmp1=n;
		while(n) { nn+=n%10; n/=10; }
		n=tmp1;
		while(n>(tmp1-500)) {
			long long tt=n;int sum=0;
			while(tt) { sum+=tt%10; tt/=10; }
			if(sum+n==tmp1) a[++cnt]=n;
			n--;
		}
		if(!cnt) {cout<<cnt<<endl;return 0;}
		cout<<cnt<<endl;
		for(register int i=cnt;i>=1;--i) cout<<a[i]<<endl;
	}
	return 0;
}

T2
Description

给出两个字符串 s,t 和一个整数 k ,进行如下操作 :

由 11 至 length(s)依次从 s 中选出 k个不相交的连续的非空子串 p1,…,pk .

由 11 至 length(t)依次从 t中选出 k 个不相交的连续的非空子串 q1,…,qk .

保持 p1,…,pk 在 s 中的相对位置顺序,保持 q1,…,qk在 t 中的相对位置顺序。

使得 p1=q1,p2=q2,…,pk=qk且最大化选出的 k 个子串的长度之和。

其中字符串从 1开始标号,length(s)表示字符串 s 的长度。
Input

第一行三个整数 n,m,k分别代表字符串 s,t的长度,选出的子串的个数。

第二行一个字符串 s .

第三行一个字符串 t .

字符串仅由小写字母构成。
Output

一行一个整数,表示选出的子串长度之和的最大值。
Sample 1
Input

15 9 4
ababaaabbaaaabb
bbaababbb

Output

8

Explanation

将字符串的每个字符从 1 开始标号。

从 s中按顺序选出的 4 个不相交的非空子串为 [2,2],[4,5],[7,8],[13,15]

从 t中按顺序选出的 4 个不相交的非空子串为 [1,1],[2,3],[4,5],[6,8]

对应字符串 : “b”,“ba”,“ab”,“abb”“b”,“ba”,“ab”,“abb”
Sample 2
http://lk.yali.edu.cn/download.php?type=problem&id=14

为防止乱搞骗分,故此题采用捆绑测试。

subtask1 20pts : n,m≤10,k≤2.

subtask2 25pts : n,m≤100,k≤3.

subtask3 25pts : n,m≤1000,k=1 .

subtask4 30pts : n,m≤1000,k≤10.

Time limit : 1s

Memory limit : 512MB

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
char a[1005],b[1005];
int n,m,k,ans,ff[1005][1005][15][2];
inline int check(int a,int b,int c,int d) {
	
}
int main() {
	cin>>n>>m>>k;
	scanf("%s%s",a+1,b+1);
	for(register int i=1;i<=n;++i)
		for(register int j=1;j<=m;++j)
			for(register int kk=1;kk<=k;++kk){
				ff[i][j][kk][1]=max(ff[i][j-1][kk][1],ff[i-1][j][kk][1]);
		//类似求最大区间和的那种处理,把前面的最大值都存储下来,免得后面用for循环查询耗时间
				if(a[i]==b[j]) {
					ff[i][j][kk][0]=max(ff[i-1][j-1][kk-1][1],ff[i-1][j-1][kk][0])+1;//这里主要是分为当前这个块是放到以前那个块中还是独自成一个新块
					ff[i][j][kk][1]=max(ff[i][j][kk][0],ff[i][j][kk][1]);
				}//取一个最大值
			}
	cout<<ff[n][m][k][1]<<endl;
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值