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;
}