第一场部分题解

PTA上的题目,邀请码是72788f48072b80c5

7-1 n个数求和

题解

加减运算前、通分前注意约分,防止溢出

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
long long int gcd(long long int a,long long int b)
{
    if(a<0)
        a=-a;
    return b==0?a:gcd(b,a%b);
}

int main()
{               int t;int i;
                long long int sumx,sumy;
                long long int l;
                long long int a;
                long long int x[105];long long int y[105];
    while(scanf("%d",&t)!=EOF)
    {
        for(i=0;i<t;i++)
        {
            scanf("%lld/%lld",&x[i],&y[i]);
            l=gcd(x[i],y[i]);
            x[i]=x[i]/l;
            y[i]=y[i]/l;
        }
        sumy=y[0]/gcd(y[0],y[1])*y[1];

        sumx=x[0]*(y[1]/gcd(y[0],y[1]))+x[1]*(y[0]/gcd(y[0],y[1]));
        l=gcd(sumx,sumy);
        sumy/=l;
        sumx/=l;
        a=sumy;
        for(i=2;i<t;i++)
        {   sumy=sumy/gcd(sumy,y[i])*y[i];
            sumx=sumx*(y[i]/gcd(a,y[i]))+x[i]*(a/gcd(a,y[i]));
            l=gcd(sumx,sumy);
            sumy/=l;
            sumx/=l;
            a=sumy;
        }
        l=sumx/sumy;
        sumx=sumx-l*sumy;
        if(l==0)
        {
            if(sumx!=0)
            printf("%lld/%lld\n",sumx,sumy);
            if(sumx==0)
            printf("0\n");
        }
        if(l!=0)
        {   if(sumx!=0)
            printf("%lld %lld/%lld\n",l,sumx,sumy);
            if(sumx==0)
            printf("%lld\n",l);
        }
        for(i=0;i<105;i++)
        {
            x[i]=0;
            y[i]=1;
        }
    }

}


7-2 比较大小

题解

直接读进数组sort就好,不过这是第一次用sort,所以多写了点方便观察sort的运行

#include<iostream>
#include <algorithm>
using namespace std;

int main()
{
    int a,b,c;
    cin>>a>>b>>c;
    int arr[3];
    arr[0]=a,arr[1]=b,arr[2]=c;
    sort(arr,arr+3);
    cout<<arr[0]<<"->"<<arr[1]<<"->"<<arr[2];
}

7-3 A-B

题解

做的时候直接O(nm)扫着删,边扫边删的话长度会动态更新,还有字符的位置也是,所以删除的时候要把索引退一位,不然会漏扫。

#include<iostream>
#include <algorithm>
#include<string>
using namespace std;

int main()
{
   string a,b;
   getline(cin,a);
   getline(cin,b);
   for(int i=0;i<b.length();++i)
   {

       for(int j=0;j<a.length();++j)
       {
           if(a[j]==b[i])
           {
              a.erase(j,1);
              j--;
           }
       }
   }
   cout<<a;
}

7-4 计算指数

题解

我很抱歉下面出现了一些奇怪的斜体或者加粗,我在努力控制正确的格式。
如果把指数看成二进制,用分治的方法,可以把复杂度从O(n)降到O(logn).
用%可以拿到最低位的数,然后用/使指数右移一位,然后对x做一个平方。
比如2的7次方
7%2是1.y=x的1次方 7/2是3,然后对x=x*x
3%2是1,y等于x的(当前index%2)* y ,然后继续保持x=x*x;
把下面的a激活就可以算base的index次方,不过a和b都需要是正整数。

#include<iostream>
#include <algorithm>
#include<string>
using namespace std;
int _exp(int base,int index)
{
    int r;
    int x=base;
    int y=1;
    while(index!=0)
    {
        r=index%2;
        index=index/2;
        if(r==1)
        {
            y*=x;
        }
        x*=x;
    }
    return y;
}
int main()
{
    int a,b;
    cin>>b;
   printf("2^%d = %d",b,_exp(2,b));
}

7-5 计算阶乘和

题解

没什么需要注意的……因为n最大是10

#include<iostream>
#include <algorithm>
#include<string>
using namespace std;
long long int jiecheng(int n)
{
    long long int i,ans=1;
    for(i=1;i<=n;++i)
    {
        ans*=i;
    }
    return ans;
}

int main()
{
    int n;
    cin>>n;
    int i;
    long long int ans=0;
    for(i=1;i<=n;++i)
    {
        ans=ans+jiecheng(i);
    }
    cout<<ans;
}

7-6 简单题

#include<iostream>
#include <algorithm>
#include<string>
using namespace std;

int main()
{
    cout<<"This is a simple problem.";
}

7-7 跟奥巴马一起画方块

题解

四舍五入可以使用int的对小数取整

#include<iostream>
#include <algorithm>
#include<string>
using namespace std;

int main()
{
   int lie;
   char c;
   cin>>lie>>c;
   int hang=(int)((lie*1.0)/2+0.5);
   for(int i=0;i<hang;++i)
   {
       for(int j=0;j<lie;++j)
       {
           cout<<c;
       }
       cout<<endl;
   }
}

7-8 查验身份证

题解

这题就申题看仔细就好了,先对前17按权重求和,接着%11后,去对应关系表里面找,也就是这个%11相当于一个索引。

#include<iostream>
#include <algorithm>
#include<string>
using namespace std;
int _right[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
char _find[11]={'1','0','X','9','8','7','6','5','4','3','2'};
bool legal(string a)
{
    int ans=0;
    bool flag=false;
    for(int i=0;i<a.length()-1;++i)
    {
        ans+=((int)(a[i]-'0')*_right[i]);
    }
  //  int asd=ans%11;
    //cout<<a[17]<<endl;
   // cout<<asd<<endl;
   // cout<<_find[ans%11]<<endl;
    if(_find[ans%11]==a[17])
    {
      //  cout<<1<<endl;
        flag=true;
    }
    return flag;
}
int main()
{
   int n;
   cin>>n;
   string a;
   int cnt=0;
   while(n--)
   {
       bool flag;
       cin>>a;
       flag=legal(a);
       if(flag==false)
       {
           cout<<a<<endl;
           cnt++;
       }
   }
   if(cnt==0)
   {
       cout<<"All passed";
   }
}

7-9 集合相似度

题解

这题我用了stl的set,因为这样可以自带去重,而且元素有序,只需要做查找相同的元素个数和不相同的总数就好了,不过并不感觉这么写有简单。。

#include<iostream>
#include <algorithm>
#include<string>
#include<set>

using namespace std;

int main()
{
    int n;
    cin>>n;
    int *num=new int[n];
    set<int> *a=new set<int>[n];
    for(int i=0;i<n;++i)
    {
        cin>>num[i];
        int temp;
        for(int j=0;j<num[i];++j)
        {
            cin>>temp;
            a[i].insert(temp);
        }
    }
//    for(int i=0;i<n;++i)
//    {
//       set<int>::iterator it;
//        for(it=a[i].begin();it!=a[i].end();++it)
//        {
//         cout<<*it<<" ";
//       }
//       cout<<endl;
//   }
    cin>>n;
    for(int i=0;i<n;++i)
    {
        int mo,mn;
        int temp1,temp2;
        int cnt=0;int _num=0;
        cin>>mo>>mn;
        temp1=mo-1;temp2=mn-1;
        set<int>::iterator it1;
        set<int>::iterator it2;
        for(it1=a[temp1].begin(),it2=a[temp2].begin();it1!=a[temp1].end()&&it2!=a[temp2].end();)
        {
            if(*it1==*it2)
            {
                ++it1;
                ++it2;
                ++cnt;
                ++_num;
            }
            else
            {
                if(*it1>*it2)
                {
                    ++it2;
                    ++_num;
                }
                else
                {
                    ++it1;
                    ++_num;
                }
            }

        }
        set<int>:: reverse_iterator _temp1=a[temp1].rbegin();
        _temp1;
        set<int>:: reverse_iterator _temp2=a[temp2].rbegin();
        _temp2;
        if(*_temp1!=*_temp2)
        {
            //cout<<*_temp1<<" "<<*_temp2<<endl;
             ++_num;
        }

        float ans=100.0*cnt/_num;
        printf("%0.2f\%\n",ans);
    }

}

7-10 中后序建树然后层次遍历

题解

这题建树的过程就是先从后序里找根,从中序里分左右子树,然后递归完成这个过程,接着用队列做一趟层次遍历。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;

const int MAXN = 1e5;
int inOrder[MAXN], postOrder[MAXN];
struct binaryNode
{
	int data;
	binaryNode *left=NULL, *right=NULL;
};

binaryNode* BuildTree(int inB, int inE, int postB, int postE)
{
	int i = 0;
	binaryNode * root = new binaryNode;
	root->data = postOrder[postE];  //后序遍历序列中获取根节点
	while (inOrder[inB + i] != root->data) i++;//中序遍历序列中查找子树根节点位置
	if (i > 0)//左子树存在
		root->left = BuildTree(inB, inB + i - 1, postB, postB + i - 1);
	if (inB + i < inE)//右子树存在
		root->right = BuildTree(inB + i + 1, inE, postB + i, postE - 1);
	return root;
}

void LevelTravel(binaryNode * root)
{
	int cnt = 0;
	queue<binaryNode *> s;
	s.push(root);
	binaryNode *temp;
	while (!s.empty())
	{
		temp = s.front();
		if (cnt == 0)
		{
			printf("%d", temp->data);
			cnt = 1;
		}
		else
		{
			printf(" %d", temp->data);
		}
		
		if (temp->left)
			s.push(temp->left);
		if (temp->right)
			s.push(temp->right);
		s.pop();

	}
}

int main()
{
	int n;
	cin >> n;
	int i = 0;
	while (cin >> postOrder[i++])
		if (cin.get() != ' ') break;
	i = 0;
	while (cin >> inOrder[i++]) //get到每次读入一行的新方法
	{
		if (cin.get() != ' ')
		{
			break;
		}	
	}
	binaryNode * root = BuildTree(0, i - 1, 0, i - 1);
	LevelTravel(root);
	DeleteTree(root);
	return 0;
}

7-11 家庭财产

题解

这题要整一个并查集,在我的另一个文章里有详解

7-12 最长对称子串

题解

这题有个诡异的地方就是a到底是对称还是不对称,如果不对称的话abc也是0,不然也是1,这是个坑。然后做的时候直接大致就是i往后走,j从0到i然后一直截取子串,判断是不是对称子串,这个好像叫马拉车算法。

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;

bool isReverse(string s)
{
	string t = s;
	reverse(t.begin(), t.end());

	if (s == t)
		return true;
	else
		return false;
}

int main()
{
	string s;//存放输入的串
	string target;//用来存放截取出来的子串
	int ans=1;//维护一个最大子串长度
	getline(cin, s);//一行读入
	for (unsigned i = 0; i < s.length(); i++)
	{
		for (int j = 0; j < i; j++)
		{
			target = s.substr(j, i+1);
			if (isReverse(target) && target.length() > ans)
			{
				ans = target.length();
				break;
			}
		}
	}
	cout << ans << endl;
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值