问题描述:输入3个子串, 输出这3个子串的最大公共子串
输入:
abcd acb abc
输出:
ab
注意:
(1)输入的字符数组以及dp数组应定义在main函数以外(全局)
(2)由于题意求的是公共字符串,而非字符串长度,因此dp数组应为string类型
#include
#include
#include
#include
using namespace std;
const int maxn=35;
char a[maxn],b[maxn],c[maxn];
string dp[maxn][maxn][maxn]; //易错点
int main(){
cin>>(a+1)>>(b+1)>>(c+1);
int len1=strlen(a+1);
int len2=strlen(b+1);
int len3=strlen(c+1);
//边界
for(int i=0;i<=len1;i++){
for(int j=0;j<=len2;j++){
for(int k=0;k<=len3;k++){
dp[i][j][0]="";
dp[i][0][k]="";
dp[0][j][k]="";
}
}
}
//状态转移方程
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++){
for(int k=1;k<=len3;k++){
if(a[i]==b[j]&&a[i]==c[k]){
dp[i][j][k]=dp[i-1][j-1][k-1]+a[i];
}else{
int l1=dp[i-1][j][k].length();
int l2=dp[i][j-1][k].length();
int l3=dp[i][j][k-1].length();
if(l1==max(l1,max(l2,l3))){
dp[i][j][k]=dp[i-1][j][k];
}else if(l2==max(l1,max(l2,l3))){
dp[i][j][k]=dp[i][j-1][k];
}else{
dp[i][j][k]=dp[i][j][k-1];
}
}
}
}
}
cout<<dp[len1][len2][len3]<<endl;
return 0;
}
题目描述:
把两个字符串变成相同的三个基本操作定义如下:
1.修改一个字符(如把a 变成b)
2.增加一个字符(如abed 变成abedd)
3.删除一个字符(如jackbllog 变成jackblog)
针对于jackbllog 到jackblog 只需要删除一个或增加一个l 就可以把两个字符串变为相同。
把这种操作需要的最小次数定义为两个字符串的编辑距离L。
编写程序计算指定文件中字符串的距离。输入两个长度不超过512 字节的ASCII 字符串,在
屏幕上输出字符串的编辑距离。
输入:
Hello world!
Hello word!
输出:
1
#include
#include
#include
using namespace std;
const int maxn=10010;
int dp[maxn][maxn];
string a,b;
int main(){
getline(cin,a);
getline(cin,b);
int len1=a.size();
int len2=b.size();
//边界
for(int i=0;i<=len1;i++){
dp[i][0]=i;
}
for(int j=0;j<=len2;j++){
dp[0][j]=j;
}
//状态转移方程
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++){
int flag=0;
if(a[i-1]!=b[j-1]){
flag=1;
}
dp[i][j]=min(dp[i-1][j-1]+flag,min(dp[i-1][j]+1,dp[i][j-1]+1));
}
}
cout<<dp[len1][len2]<<endl;
return 0;
}
问题描述
Hanoi 塔问题是印度的一个古老的传说。开天辟地的神勃拉玛在一个庙里留下了三根金刚石的棒,第一根上面套着64 个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用中间的一根棒作为帮助,但每次只能搬一个,而且大的不能放在小的上面。
请编写程序,把A 柱上的n 个金片,搬动到C 柱(中间可以使用B 柱),使得搬动的次数最少。输入金片的个数n(1<=n<=64),输出总搬动次数,以及最后100 次搬动。如果搬动次数小于等于100 则全部输出;每个搬动占一行,加上是这第几次搬动的数字和”:”,格式见示例。
输入:
2
输出:
3
1:A->B
2:A->C
3:B->C
#include
#include
using namespace std;
int acount=1,count=0;
void hanoi(int n,char a,char b,char c){
if(n==1){
if((acount-count++)<=100){
cout<<count<<":"<<a<<"->"<<c<<endl;
}
}else{
hanoi(n-1,a,c,b);
if((acount-count++)<=100){
cout<<count<<":"<<a<<"->"<<c<<endl;
}
hanoi(n-1,b,a,c);
}
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++){
acount*=2;
}
acount--;
cout<<acount<<endl;
hanoi(n,'A','B','C');
return 0;
}
题目描述:给定两个字符串,求最大公共字串的长度,长度小于1000
分为两种问题:要求计算连续最长字串的长度
如下按照寻找连续的字串理解
输入:
1111hello2222
1133hello444
输出:
5
注意:公共子串是连续的,如果求不连续,用算法笔记上P435的做法
#include
#include
#include
#include
using namespace std;
const int N = 1000;
int dp[N][N] = {0};
int main(){
string A, B;
getline(cin, A);
getline(cin, B);
int l1 = A.length();
int l2 = B.length();
int ans = 0;
for(int i = 0; i < l1; i++){
for(int j = 0; j < l2; j++){
if(A[i] != B[j]){ //两个字符不同
dp[i][j] = 0;
}
else if(i == 0 || j == 0){ //字符相同,而且是第一个字符
dp[i][j] = 1;
if(ans < 1)
ans = 1;
}
else{ //字符相同,均不是第一个字符
dp[i][j] = dp[i - 1][j - 1] + 1;
if(dp[i][j] > ans){
ans = dp[i][j];
}
}
}
}
cout << ans << endl;
return 0;
}
问题描述:有2n 的地板,用12和 2*1 的骨牌进行铺地板。问共有多少种情况。结果对 999983 取余,1<=n<=10000
输入:
6
输出:
13
#include
using namespace std;
const int maxn=10010;
int dp[maxn];
int main()
{
int n;
cin>>n;
dp[1]=1;
dp[2]=2;
for(int i=3;i<=n;i++){
dp[i]=dp[i-2]+dp[i-1]%999983;
}
cout<<dp[n]<<endl;
return 0;
}
题目描述:给定一个数组及其大小,数组元素在[-106,106],元素个数最多 10^6 个。输出最大的连续子序列和,题目保证最后结果为正数。
#include
#include
using namespace std;
const int maxn=1000010;
int A[maxn],dp[maxn];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>A[i];
}
//边界
dp[0]=A[0];
for(int i=1;i<n;i++){
//状态转移方程
dp[i]=max(A[i],dp[i-1]+A[i]);
}
int max=0;
for(int i=0;i<n;i++){
if(dp[i]>max){
max=dp[i];
}
}
if(max>0)
cout<<max<<endl;
else
cout<<"No existence"<<endl;
return 0;
}
问题描述:输入树的中序和后序排列,输出树的层次遍历
输入:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出:
4 1 6 3 5 7 2
#include
#include
using namespace std;
struct node{
int data;
node* lchild;
node* rchild;
};
int n,post[35],in[35];
node* create(int postL,int postR,int inL,int inR){ //后序和中序构造二叉树
if(postL>postR){
return NULL;
}
node* root=new node;
root->data=post[postR];
int k;
for(k=inL;k<=inR;k++){
if(in[k]==post[postR])
break;
}
int numleft=k-inL;
root->lchild=create(postL,postL+numleft-1,inL,k-1);
root->rchild=create(postL+numleft,postR-1,k+1,inR);
return root;
}
int num=0;
void LayerOrder(node* root){ //层序遍历
queue<node*> q;
q.push(root);
while(!q.empty()){
node* now=q.front();
q.pop();
printf("%d",now->data);
num++;
if(num<n)
printf(" ");
if(now->lchild!=NULL){
q.push(now->lchild);
}
if(now->rchild!=NULL){
q.push(now->rchild);
}
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&post[i]);
}
for(int i=0;i<n;i++){
scanf("%d",&in[i]);
}
node* root=create(0,n-1,0,n-1);
LayerOrder(root);
printf("\n");
return 0;
}
问题描述:二叉树问题。比如节点是ABCDE编号是01234,给出每个左右子树的编号。求最大叶子间距。
输入1:
3
1 2
-1 -1
-1 -1
输出1:
2
输入2:
6
1 -1
2 3
4 -1
-1 5
-1 -1
-1 -1
输出2:
4
#include
const int maxn=100;
struct node{
int lchild,rchild;
}Node[maxn];
int maxd; //全局变量记录最大叶子间距
//求最大叶子间距
int maxDistance(int root,int &maxd){
if(root==-1)
return -1;
int lefth=maxDistance(Node[root].lchild,maxd)+1;
int righth=maxDistance(Node[root].rchild,maxd)+1;
if(lefth+righth>maxd){
maxd=lefth+righth;
}
return lefth>righth?lefth:righth; //返回的是当前结点为根时的深度
}
int main(){
int n,left,right;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d %d",&left,&right);
Node[i].lchild=left;
Node[i].rchild=right;
}
maxDistance(0,maxd);
printf("%d\n",maxd);
return 0;
}
题目描述:
输入一棵二叉树,输出树的前、中、后序遍历结果。
输入一个整数N(N<= 10000),表示树中有N个结点(编号0~N-1)。
接下来N行,依次为结点0~结点N-1的左右孩子情况。
每行3个整数,F,L,R。L,R为F的左右孩子。L,R如果为-1表示该位置上没有孩子。
分三行分别输出树的前中后序遍历。
同一行中的数字,用一个空格间隔。
输入:
5
0 3 1
1 2 -1
2 -1 4
3 -1 -1
4 -1 -1
输出:
0 3 1 2 4
3 0 2 4 1
3 4 2 1 0
#include
const int maxn=10010;
struct node{
int lchild,rchild;
}Node[maxn];
int n,num=0;
bool flag[maxn]={false};
void print(int id){
printf("%d",id);
num++;
if(num<n)
printf(" ");
else
printf("\n");
}
void preOrder(int root){
if(root==-1)
return;
print(root);
preOrder(Node[root].lchild);
preOrder(Node[root].rchild);
}
void inOrder(int root){
if(root==-1)
return;
inOrder(Node[root].lchild);
print(root);
inOrder(Node[root].rchild);
}
void postOrder(int root){
if(root==-1)
return;
postOrder(Node[root].lchild);
postOrder(Node[root].rchild);
print(root);
}
int main(){
int x,left,right;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d%d",&x,&left,&right);
Node[x].lchild=left;
Node[x].rchild=right;
flag[left]=true;
flag[right]=true;
}
int root;
for(int i=0;i<n;i++){
if(flag[i]==false){
root=i;
}
}
preOrder(root);
num=0;
inOrder(root);
num=0;
postOrder(root);
return 0;
}
题目描述:给定二叉树的节点总数 n,输出二叉树形态总数,n<= 1000
输入:
3
输出:
5
#include
long long function(int n){ //防止阶乘的结果溢出,使用long long型
long long res;
if(n==0)
res=0;
else if(n==1)
res=1;
else{
res=n;
while(n>1){
res=res*(n-1);
n--;
}
}
return res;
}
int main(){
int n;
long long result;
scanf("%d",&n);
result=function(2*n)/function(n)/function(n+1);
printf("%lld\n",result);
return 0;
}
题目描述:给出优先队列的实现,实现4个操作
• ADD(N,P):往队列里加入id为N的优先级为P的任务
• NEXT:输出下一个最高优先级的任务的id,如果优先级相同输出id小的任务,若队列中没有任务输出-1
• REMOVE(N):移除id为N的任务
• COUNT:输出队列中的任务数量
#include
#include
#include
#include
#include
using namespace std;
struct node{
int id;
int p; //优先级
};
struct cmp{
bool operator()(node a,node b){
if(a.p!=b.p)
return a.p<b.p;
else
return a.id>b.id;
}
};
priority_queue<node,vector<node>,cmp> q;
priority_queue<node,vector<node>,cmp> temp; //临时优先队列
void add(int id,int p){
node a;
a.id=id;
a.p=p;
q.push(a);
}
void next(){
node a;
a=q.top();
cout<<a.id<<" "<<a.p;
}
void remove(int id){
node a=q.top();
while(a.id!=id){
node b=a;
q.pop();
temp.push(b);
}
}
int main(){
int id,p;
string str;
cin>>str;
while(1){
if(str=='ADD'){
scanf("%d%d",&id,&p);
add(id,p);
}else if(str=='NEXT'){
next();
}else if(str=='REMOVE'){
scanf("%d",&id);
remove(id);
}else if(str=='COUNT'){
int num=q.size();
cout<<num<<endl;
}else
break;
}
return 0;
}
题目描述:
给定一个后缀序列,要求求值,只有加减
输入:
123++4-
输出:
2
#include
#include
#include
using namespace std;
stack<int> s;
int main(){
string str;
cin>>str;
int k;
for(int i=0;i<str.size();i++){
if(str[i]>='0'&&str[i]<='9'){
int temp=str[i]-'0';
s.push(temp);
}else if(str[i]=='+'){
int a=s.top();
s.pop();
int b=s.top();
s.pop();
k=b+a;
s.push(k);
}else if(str[i]=='-'){
int a=s.top();
s.pop();
int b=s.top();
s.pop();
k=b-a;
s.push(k);
}
}
cout<<s.top()<<endl;
return 0;
}
题目描述:给定一个字符串(长度不超过100),求哈夫曼编码的最短长度。
输入1:
abbcccdddd
输出1:
19
输入2:
we will we will r u
输出2:
50
主要思想:优先队列+map数组+栈
#include
#include
#include
#include
#include
using namespace std;
map<char,int> mp;
priority_queue<int,vector<int>,greater<int>> q;
string str;
int main(){
getline(cin,str);
int len=str.length();
for(int i=0;i<len;i++){
if(mp.find(str[i])==mp.end()){
mp[str[i]]=1;
}else
mp[str[i]]++;
}
for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++){
q.push(it->second);
}
int ans=0;
while(q.size()!=1){
int temp;
int a=q.top();
q.pop();
int b=q.top();
q.pop();
temp=b+a;
ans+=temp;
q.push(temp);
}
cout<<ans<<endl;
return 0;
}
题目描述:给一个表,问两个位置之间的最短距离是多少,其中素数位置不能经过。
输入:
3
1 4
9 32
10 12
输出:
Case 1: 1
Case 2: 7
Case 3: impossible
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3
using namespace std;
const int maxn=410;
int g[maxn][maxn];
int vis[maxn][maxn];
const int mov[4][2]= {{-1,0},{1,0},{0,-1},{0,1}};
bool isPrime(int v)
{
int ed=sqrt(v);
for(int i=2; i<=ed; ++i)
if(v%i==0) return false;
return true;
}
int nextDir(int d)
{
if(d==RIGHT) return UP;
else if(d==UP) return LEFT;
else if(d==LEFT) return DOWN;
else if(d==DOWN) return RIGHT;
}
pair<int,int> pos[10005];
void init()
{
int val=0;
int x=200,y=200;
g[x][y]=++val;
pos[val]=make_pair(x,y);
int d=RIGHT;
int len=2;
while(len<=105)
{
for(int i=1; i<len; ++i)
{
x=x+mov[d][0];
y=y+mov[d][1];
++val;
if(isPrime(val)) g[x][y]=0;
else
{
g[x][y]=val;
if(val<=10000)
pos[val]=make_pair(x,y);
}
}
d=nextDir(d);
for(int i=1; i<len; ++i)
{
x=x+mov[d][0];
y=y+mov[d][1];
++val;
if(isPrime(val)) g[x][y]=0;
else
{
g[x][y]=val;
if(val<=10000)
pos[val]=make_pair(x,y);
}
}
d=nextDir(d);
++len;
}
}
int bfs(int st,int ed)
{
memset(vis,0,sizeof(vis));
queue<pair<int,int> > que;
que.push(pos[st]);
while(!que.empty())
{
pair<int,int> p=que.front();
que.pop();
for(int i=0; i<4; ++i)
{
int nx=p.first+mov[i][0],ny=p.second+mov[i][1];
if(vis[nx][ny]||g[nx][ny]==0) continue;
vis[nx][ny]=vis[p.first][p.second]+1;
if(g[nx][ny]==ed) return vis[nx][ny];
que.push(make_pair(nx,ny));
}
}
return -1;
}
int main()
{
init();
int x,y,kase=0;
while(scanf("%d%d",&x,&y)!=EOF)
{
printf("Case %d: ",++kase);
if(x==y) printf("0\n");
else
{
int ans=bfs(x,y);
if(ans==-1) puts("impossible");
else printf("%d\n",ans);
}
}
return 0;
}
题目描述:大家一定都能熟练掌握二分查找啦!那么来计算二分的次数吧!约定二分的中点mid = (left + right) / 2。
输入
第一行输入一个整数N(N<=10000)。
第二行输入N个升序整数。
第三行输入一个待查找的整数(必定在第二行中出现过)。
输出
输出二分查找该整数时,进行过多少次二分。
输入:
5
18 53 54 74 99
53
输出:
2
#include
#include
using namespace std;
int count=0,input[10001];
void search(int s,int e,int key)
{
count++;
int mid=(s+e)/2;
if(input[mid]==key) return;
else if(input[mid]>key) search(s,mid,key);
else search(mid,e,key);
}
int main()
{
freopen("p1.in","r",stdin);
freopen("p1.out","w",stdout);
int N,key;
cin>>N;
for(int i=0;i<N;i++) cin>>input[i];
cin>>key;
search(0,N-1,key);
cout<<count<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
问题描述:排序问题:1000个成绩输出前30%。
我这里输入十组数据,输出前3个
思路:
采用堆排序最佳。
#include
#include
using namespace std;
//给定十个元素输出最大的前三个,元素从下标1开始存储
int heap[11] = {0, 3, 1, 2, 6, 5, 4, 9, 8, 7, 10};
int n = 10; //元素个数
//对heqap数组在loe和high范围内进行调整
//low为父节点,high一般为堆的最后一个元素下标
void downAdjust(int low, int high){
int i = low, j = i * 2; //i为调整节点,j为左孩子
while(j <= high){ //如果存在左孩子
if(j + 1 <= high && heap[j + 1] > heap[j]){ //如果右孩子存在,且值大于左孩子
j = j + 1; //j来存储右孩子下标
}
//孩子中最大的权值大于要调整的节点
if(heap[j] > heap[i]){
swap(heap[j], heap[i]);
i = j; //继续调整以j为父节点的子树
j = i * 2;
}
else
break;
}
}
//建树
void createHeap(){
for(int i = n / 2; i >= 1; i--){ //i从第一个非叶节点开始,直到根结点
downAdjust(i, n);
}
}
void heapSort(){
createHeap(); //建堆
printf("%d", heap[1]); //输出第一个最大值
for(int i = n; i > 8; i--){ //倒着枚举,直到输出符合题目要求的数量
swap(heap[i], heap[1]); //交换heap[i]与堆顶
downAdjust(1, i - 1); //调整堆顶
printf(" %d", heap[1]); //调整过后,堆顶元素为最大值,输出
}
printf("\n");
}
int main(){
heapSort();
return 0;
}
题目描述:给一个字符串比如ABC 再给一个整数比如3输出AAABBBCCC就行了。
#include
#include
#include
using namespace std;
int main(){
string str;
getline(cin, str);
int n;
cin >> n;
for(int i = 0; i < str.size(); i++){
for(int j = 0; j < n; j++){
printf("%c", str[i]);
}
}
printf("\n");
return 0;
}
题目描述:对于主串M和模式串P,找到P在M中出现的所有子串的第一个字符在P中的位置。P中第一个字符所在的位置为0。首行的数字表示有多少组字符串。
输入:
2
ababababa
ababa
aaa
aa
输出:
0 2 4
0 1
(相邻位置之间用一个空格隔开)
#include
#include
#include
char str1[100],str2[100];
int main()
{
int n;
scanf("%d",&n);
while(n--){
memset(str1,0,sizeof(str1));
memset(str2,0,sizeof(str2));
scanf("%s",str1);
scanf("%s",str2);
int len1=strlen(str1);
int len2=strlen(str2);
int idx;
for(int i=0;i<len1;i++){
if(str1[i]!=str2[0])
continue;
idx=i;
if(len1-i<len2)break;
for(int j=0;j<len2;j++){
if(str1[i]!=str2[j])
break;
i++;
if(j=len2-1)
printf("%d ",idx);
}
i=idx;
}
}
system("pause");
return 0;
}
题目描述:给出四个正方体箱子的边长,问能装下这四个正方体箱子的大正方体边长最小要多大,要求边长最小且必须能装下四个箱子。
输入:
2
2 2 2 2
输出:
4
#include
#include
#include
using namespace std;
int main()
{
int a[4],cas = 1;
int x,y,ans;
while(~scanf("%d%d%d%d",&a[0],&a[1],&a[2],&a[3]))
{
sort(a,a+4);
printf("Case %d: %d\n",cas++,a[2]+a[3]);
}
return 0;
}
题目描述:给出长方形的长和宽,每次从长方形里撕去最大的正方形,输出最后能得到多少正方形
输入:
3 4
输出:
4
#include
#include
using namespace std;
int main(){
int a, b; //a 长 , b 宽
scanf("%d%d", &a, &b);
int ans = 0;
while(a != b){
ans++;
if(a < b){
swap(a, b);
}
a = a - b;
}
printf("%d", ans + 1);
return 0;
}
题目描述:给出a,b,c(3个整数),判断a,b能否通过±*/得到c,ab可以交换位置,可以输出YES,不行输出NO
输入:
3 8 2
输出:
NO
#include
int main(){
long long a, b, c;
scanf("%lld%lld%lld", &a, &b, &c);
if(a + b == c || a * b == c){
printf("YES\n");
}
else if(a - b == c || b - a == c){
printf("YES\n");
}
else if(a / b == c || b / a == c){
printf("YES\n");
}
else{
printf("NO\n");
}
return 0;
}
题目描述:给定两个字符串,求最大公共字串的长度,长度小于1000
分为两种问题:要求计算连续最长字串的长度
如下按照寻找连续的字串理解
输入:
1111hello2222
1133hello444
输出:
5
#include
#include
#include
#include
using namespace std;
const int N = 1000;
int dp[N][N] = {0};
int main(){
string A, B;
getline(cin, A);
getline(cin, B);
int l1 = A.length();
int l2 = B.length();
int ans = 0;
for(int i = 0; i < l1; i++){
for(int j = 0; j < l2; j++){
if(A[i] != B[j]){ //两个字符不同
dp[i][j] = 0;
}
else if(i == 0 || j == 0){ //字符相同,而且是第一个字符
dp[i][j] = 1;
if(ans < 1)
ans = 1;
}
else{ //字符相同,均不是第一个字符
dp[i][j] = dp[i - 1][j - 1] + 1;
if(dp[i][j] > ans){
ans = dp[i][j];
}
}
}
}
cout << ans << endl;
return 0;
}
题目描述:给定一个整数序列,求中位数。如果序列个数为奇数,中位数为升序的中间位置,如果是偶数,这位升序的中间两个数的平均值。
输入
输入包含多组测试数据,每一组第一行为n(n<104)表示这个序列的个数,接下来有n个整数k(0
输出
输出这个序列的中位数
输入1:
5
2 1 4 3 5
输出1:
3
输入2:
4
1 4 3 2
输出2:
3
#include
#include
using namespace std;
const int N = 10010;
int num[N];
int main(){
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++){
scanf("%d", &num[i]);
}
sort(num, num + n);
if(n % 2 == 0){ //n为偶数
if((num[n / 2] + num[n / 2 - 1]) % 2 == 0){ //中间两位平均值为整数
printf("%d\n", (num[n / 2] + num[n / 2 - 1]) / 2);
}
else{
printf("%.lf\n", (num[n / 2] + num[n / 2 - 1]) / 2.0);
}
}
else{ //n为奇数
printf("%d\n", num[n / 2]);
}
return 0;
}
题目描述:给定一个9位数字的ISBN,求其校验位。ISBN格式为2-02-033598,校验位的计算方法如下:从左到右依次将各位数字乘10,9,8,……,2,求出其和S,作模运算得M=S mod 11。若11-M在1和9之间,校验位即为该数字;若11-M等于10,校验位为X;11-M等于11,校验位为0。输出添加校验位的ISBN,如2-02-033598-0。
输入1:
2-02-033598
输出1:
2-02-033598-0
输入2:
7-309-04547
输出2:
7-309-04547-5
#include
#include
char str[15];
int a[10];
int main(){
scanf("%s", str);
int count = 0;
for(int i = 0; i < 11; i++){
if(str[i] != '-'){
a[count++] = str[i] - '0';
}
}
int s = 0;
int d = 10;
for(int i = 0; i < 9; i++){
s += a[i] * d;
--d;
}
int m = s % 11;
int t = 11 - m;
if(t < 10){
printf("%s-%d\n", str, t);
}
else if(t == 10){
printf("%s-X\n", str);
}
else{
printf("%s-0\n", str);
}
return 0;
}
题目描述:众数就是一个序列中出现次数最多的数字。 如果不唯一,则输出小的那个值。
样例输入:
第一行给出N(1<=n<=10^5 ),第二行给出N个数字,每个数字在int范围内
输入1:
8
10 3 8 8 3 2 2 2
输出1:
2
输入2:
5
3 3 2 4 2
输出2:
2
#include
#include
#include
using namespace std;
map<int, int> mp;
int main(){
int n, x;
int maxn = 0;
int maxp;
scanf("%d", &n);
for(int i = 0; i < n; i++){
scanf("%d", &x);
if(mp.find(x) != mp.end()){ //这个数已经出现过
mp[x]++;
}
else{
mp[x] = 1;
}
}
for(map<int, int>::iterator it = mp.begin(); it != mp.end(); it++){
if(it->second > maxn){ //已经从小到大排好序,取>即可
maxn = it->second; //众数出现的次数
maxp = it->first; //众数的值
}
}
printf("%d", maxp);
题目描述:解方程,给定一个字符串,代表一个一元一次方程。如果有解求解,输出格式“x=数字“,如果解的个数无穷,输出 “infinite solutions”。如果没有解输出“no solution”,字符串长度不超过 256 。
输入:
2x+4-3x=x-2
输出:
x=2
#include
#include
#include
using namespace std;
string str;
int main(){
cin >> str;
int a = 0, b = 0; //系数、常数
int sym = 1, flag = 1; //sym表示数字之前的符号,flag表示等号的左右(初始值为1,表示在左面)
int i = 0; //访问字符串的下标
while(i < str.size()){
if(str[i] == '='){
sym = 1;
flag = -1;
}
else if(str[i] == '+'){
sym = 1;
}
else if(str[i] == '-'){
sym = -1;
}
else{ //遇到数字或者x
int t = 0; //暂存遇到的数字值
while(i < str.size() && str[i] >= '0' && str[i] <= '9'){ //遇到数字,计算数值
t = 10 * t + (str[i] - '0');
++i;
}
//当表达式最后一位是数字时,比如2x+4-3x=x-2,上面while的循环会使i >= str.size()成立
if(i >= str.size()){
b -= t * sym;
break;
}
if(str[i] == 'x' && t == 0){ //如果x之前的系数为正负1时,要单独判断,因为此时t=0
a += sym * flag;
}
else if(str[i] == 'x'){ //处理系数
a += t * sym * flag;
}
else{ //处理常数
b += t * sym * flag;
continue; //直接进行下一次循环是因为:上面while循环中处理数字之后已经++i
}
}
i++;
}
if(a == 0 && b == 0){
printf("infinite solutions\n");
}
else if(a != 0 && b % a == 0){
printf("x=%d\n", -b/a);
}
else{
printf("no solution\n");
}
return 0;
}
题目描述:输入日期格式:YYYYMMDD,求与20190205的相隔的天数。
输入:20190208
输出:3
#include
#include
#include
using namespace std;
//month[2][0]平年, month[2][1]闰年
int month[13][2] = {{0,0}, {31, 31}, {28,29}, {31,31}, {30,30}, {31, 31}, {30,30},{31, 31}, {31, 31}, {30,30}, {31, 31},{30,30},{31, 31}} ;
bool isLeapYear(int year){
if(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)){
return true;
}
return false;
}
int main(){
int time1, time2 = 20190205;
scanf("%d", &time1);
if(time1 > time2){
swap(time1, time2);
}
int y1, m1, d1, y2, m2, d2;
y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100;
y2 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100;
int num = 0;
while(y1 < y2 || m1 < m2 || d1 < d2){
d1++;
num++;
if(d1 == month[m1][isLeapYear(y1)] + 1){
m1++;
d1 = 1;
}
if(m1 == 13){
y1++;
m1 = 1;
}
}
cout << num << endl;
return 0;
}
题目描述:给定五个 0~9 范围内的整数 a1, a2, a3, a4, a5。如果能从五个整数中选出三个并且这三个整数的和为10 的倍数(包括 0),那么这五个整数的权值即为剩下两个没被选出来的整数的和对 10 取余的结果,显然如果有多个三元组满⾜和是 10 的倍数,剩下两个数之和对 10 取余的结果都是相同的;如果
选不出这样三个整数,则这五个整数的权值为 -1。
现在给定 T 组数据,每组数据包含五个 0~9 范围内的整数,分别求这 T 组数据中五个整数的权值。
【输入格式】 第一行一个整数 T (1<=T<=1000),表⽰数据组数。 接下来 T 行,每行 5 个 0~9 的整数,表示一组数据。
【输出格式】输出 T 行,每行一个整数,表⽰每组数据中五个整数的权值。
#include
#include
#include
using namespace std;
//回溯法得到其中三数之和,若没有10的倍数,返回-1
int judge(int sum,vector<int>& visited,vector<int>D,int num) {
if (num > 3) return -1;
if (num == 3 && sum % 10 == 0) return sum;
for (int i = 0; i < D.size(); i++) {
if (visited[i] == 0) {
visited[i] = 1;
int f = judge(sum + D[i], visited, D, num + 1);
if (f != -1) return f;
visited[i] = 0;
}
}
return -1;
}
int main()
{
int T;
cin >> T;
int N = 5;
vector<vector<int>>data(T, vector<int>(N));
for (int i = 0; i < T; i++) {
for (int j = 0; j < N; j++) {
cin >> data[i][j];
}
}
vector<int>result;
vector<int> visited(N, 0); //记录已被访问过的数
for (int i = 0; i < T; i++) {
int sum = 0, num = 0;
fill(visited.begin(), visited.end(), 0);
int flag = judge(sum, visited, data[i], num);
if (flag != -1) { //存在三数之和为10的倍数
int S = 0;
for (int j = 0; j < N; j++) S += data[i][j];
result.push_back((S - flag) % 10); //总和减去三数之和就是剩余两数之和
}
else result.push_back(flag);
}
for (int i = 0; i < result.size(); i++) cout << result[i] << endl;
}
题目描述:给定 n 个整数 a1, a2, …, an 和⼀个 d,你需要选出若⼲个整数,使得将这些整数从⼩到⼤排好序之后,任意两个相邻的数之差都不⼩于给定的 d,问最多能选多少个数出来。
【输⼊格式】 第⼀⾏两个整数 n,d (1<=n<=10^5, 0<=d<=10^9),分别表⽰整数个数和相邻整数差的下界。 第⼆⾏ n
个整数 a1, a2, …, an (1<=ai<=10^9, 1<=i<=n),表⽰给定的 n 个整数。
【输出格式】 仅⼀⾏⼀个整数,表⽰答案。
#include
#include
#include
using namespace std;
int main()
{
int n, d;
cin >> n >> d;
vector<int>data(n);
for (int i = 0; i < data.size(); i++) cin >> data[i];
sort(data.begin(), data.end()); //从小到大排序
int num = 0;
if (n < 2) { //只有一个整数
cout << num << endl;
return 0;
}
for (int i = 0, j = 1; j < data.size();) {
if (data[j] - data[i] >= d) {
num++;
i = j;
j++;
}
else j++;
}
if (num == 0) cout << num << endl; //没有符合条件的数
else cout << num + 1 << endl; //由于每次只将较小的数加入结果集,因此最后还需将最后的大数加入结果集
return 0;
}
题目描述:下课了,有 n 位同学陆续赶到⻝堂进⾏排队打饭,其中第 i 位同学的到达时间为 ai,打饭耗时为 ti,等待时间上限为 bi,即如果其在第 ai+bi 秒的时刻仍然没有轮到他开始打饭,那么他将离开打饭队列,另寻吃饭的地⽅。问每位同学的开始打饭时间,或者指出其提前离开了队伍(如果这样则输出 -1)。
【输⼊格式】 第一行一个整数 n (1<=n<=105),表⽰来打饭的同学数量。 接下来 n行,每⾏三个整数 ai,ti,bi (1<=ai,ti,bi<=10^9, 1<=i<=n),分别表⽰每位同学的到达时间、打 饭耗时、等待时间上限。 保证 a1
#include
#include
#include
using namespace std;
int main()
{
int n;
cin >> n;
vector<vector<long long int>>data(n, vector<long long int>(3));
for (int i = 0; i < data.size(); i++){
for (int j = 0; j < data[i].size(); j++) {
cin >> data[i][j];
}
}
long long int endtime = 0; //记录上一个学生打饭结束的时间
vector<long long int>result;
for (int i = 0; i < data.size(); i++) {
if (data[i][0] >= endtime) { //第i位学生达到时无人打饭,可以直接开始打饭
result.push_back(data[i][0]);
endtime = data[i][0] + data[i][1];
}
else { //第i位学生正好有人打饭,那么第i位学生的等待时间=上一位学生的结束时间-第i位学生的开始时间
if (endtime - data[i][0] > data[i][2]) result.push_back(-1);
else {
result.push_back(endtime);
endtime = endtime + data[i][1];
}
}
}
for (int i = 0; i < result.size(); i++) cout << result[i] << ' ';
return 0;
}
题目描述:给定⼀个 1-n 的排列 P,即⻓度为 n,且 1~n 中所有数字都恰好出现⼀次的序列。现在按顺序将排列中的元素⼀⼀插⼊到初始为空的⼆叉搜索树中(左小右大),问最后每个节点的⽗亲节点的元素是什么。特别地,根节点的⽗亲节点元素视为 0。
【输⼊格式】
第⼀⾏⼀个整数 n (1<=n<=10^5),表⽰排列 P 中的元素个数。
第⼆⾏ n 个整数 p1, p2, …, pn (1<=pi<=n, 1<=i<=n),表⽰给定的排列。
【输出格式】 ⼀⾏ n 个整数,其中第 i 个整数 ai 表⽰元素 i 对应节点的⽗亲节点的元素。特别地,根节点的⽗亲节 点元素视为 0。
#include
#include
#include
#include
using namespace std;
int main(){
int n;
cin >> n;
vector<int>father(n + 1);
map<int, int>dict;
dict[0] = 0;
int maxn = 0;
for (int i = 0; i < n; i++) {
int t;
cin >> t;
if (t > maxn) {
father[t] = maxn;
dict[t] = dict[maxn] + 1;
maxn = t;
}
else {
map<int, int>::iterator small = dict.upper_bound(t);
map<int, int>::iterator big = small--;
if (big->second > small->second) {
father[t] = big->first;
dict[t] = big->second + 1;
}
else {
father[t] = small->first;
dict[t] = small->second + 1;
}
}
}
for (int i = 1; i < father.size(); i++) cout << father[i] << ' ';
}
题目描述:给定⼀个⻓为 n 的序列 A,其中序列中的元素都是 0~9 之间的整数,对于⼀个⻓度同样为 n 整数序列B,定义其权值为 |A_i-B_i| (1<=i<=n) 之和加上 (B_j-B_j+1)^2 (1<=j
【输出格式】仅⼀⾏⼀个整数,表⽰答案。
#include
#include
#include
#include
#include
using namespace std;
#define N 10
int main() {
int n;
cin >> n;
vector<int>A(n);
for (int i = 0; i < A.size(); i++) cin >> A[i];
vector<vector<int>>dp(n, vector<int>(N, INT_MAX));
for (int i = 0; i < N; i++) dp[0][i] = abs(i - A[0]);
for (int i = 1; i < A.size(); i++) {
for (int j = 0; j < N; j++) {
for (int k = 0; k < N; k++) {
dp[i][j] = min(dp[i][j], dp[i - 1][k] + abs(A[i] - j) + (j - k)*(j - k));
}
}
}
int result = INT_MAX;
for (int i = 0; i < N; i++) result = min(result, dp[n - 1][i]);
cout << result;
return 0;
}
温馨提示:资源整理不易,看到最后,记得一键三连奥,笔芯!!!