【PAT刷题】快速产出垃圾——2020-3-4

B1040/A1093

(1)参考答案

 1 #include <cstdio>
 2 #include <cstring>
 3 const int MAXN =100010;
 4 const int MOD = 1000000007;
 5 char str[MAXN];
 6 int leftNumP[MAXN] ={0};
 7 int main(){
 8     scanf("%s",str);
 9     int len = strlen(str);
10     
11     for(int i=0;i<len;i++){
12         if(i>0){
13             leftNumP[i] = leftNumP[i-1];
14         }
15         if(str[i] == 'P'){
16             leftNumP[i]++; 
17         }
18     }
19     int ans= 0,rightNumT=0;
20     for(int i=len-1;i>=0;i--){
21         if(str[i] == 'T'){
22             rightNumT++;
23         }
24         else if(str[i]=='A'){
25             ans = (ans+leftNumP[i]*rightNumT)%MOD;
26         }
27     }
28     printf("%d\n",ans);
29     return 0;
30 }

这写法很厉害很值得学习。

总之就是先从左到右看每一位有多少个P,后一位的P由前一位构成。

然后从右往左,因为T也同样有继承前边的性质,所以遇到T就加,遇到A就计算就好了。

 

A1010

思路

步骤1:将已经确定进制的数放在N1,将未确定进制的数放在N2,以便后面进行统一计算。

步骤2:将N1转换为十进制,使用long long类型进行存储。

(1)自己尝试

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 
 8 int findMax(char n[]){
 9    int len = strlen(n);
10    int max = -1;
11    for(int i=0;i<len;i++){
12         if(n[i]>='a' && n[i]<='z'){
13             if(n[i]-'a'+10>max) max = n[i]-'a'+10;
14         }
15         else{
16             if(n[i]-'0'>max) max = n[i]-'0';
17         }
18    }
19     return max+1;
20 }
21 
22 LL toTen(char n2[],LL rdx){
23     int len = strlen(n2);
24     LL ans=0;
25     for(int i=0;i<len;i++){
26         if(n2[i]>='a' && n2[i]<='z'){
27             ans=(n2[i]-'a'+10)+ans*rdx;
28         }
29         else{
30             ans= (n2[i]-'0')+ans*rdx;
31         }
32         if(ans<0 || ans > (1LL<<63)-1) return -1;
33     }
34     return ans;
35 }
36 
37 LL search(char n2[],LL left,LL right,int n){
38     while(left<=right){
39         LL mid = (left+right)/2;
40         if(toTen(n2,mid)==n) return mid;
41         else if(toTen(n2,mid)>n || toTen(n2,mid)<0){
42             right =mid-1;
43         }
44         else{
45             left = mid+1;
46         }
47     }
48     return -1;
49 }
50 
51 int main(){
52     char n1[20];
53     char n2[20];
54     int tag,radix;
55     scanf("%s %s %d %d",n1,n2,&tag,&radix);
56     if(tag == 2){
57         char tmp[20];
58         strcpy(tmp,n1);
59         strcpy(n1,n2);
60         strcpy(n2,tmp);
61     }
62     LL max2 = findMax(n2);
63     LL n = toTen(n1,radix);
64     LL high = max(max2,n)+1;
65     LL ans = search(n2,max2,high,n);
66     if(ans==-1) printf("Impossible");
67     else printf("%lld",ans);
68 }

只拿了24分,测试点10没过。暂时先放弃了。

踩的坑主要是溢出和进制范围上限,很讨厌的数学题,需要找回一下做数学的状态。

 

A1044

超时了也没啥办法,看答案

(1)参考答案

思路

令Sum[i]标识A[1]到A[i]的和值。要注意序列都是正值,因此Sum[i]一定是单调递增的。这样做的好处在于,如果要求连续子序列A[i]到A[j]的和值,只需要计算Sum[j]-Sum[i-1]即可。(类似数列求和)

既然Sum数组严格单调递增,那就可以用二分法来做这道题。假设需要在序列A[1]~A[n]中寻找和为S的连续子序列,就可以枚举左端点i(1<=i<=n),然后在Sum数组的[I,n]范围内查找值为Sum[i-1]+S的元素(由Sum[j]-Sum[i-1]=S推得)是否存在。

 1 #include <cstdio>
 2 const int N = 100010;
 3 int sum[N];
 4 int n,S,nearS = 100000010;
 5 
 6 //upper_bound函数返回在[L,R)内第一个大于x的位置
 7 int upper_bound(int L,int R,int x){
 8     int left = L,right= R,mid;
 9     while(left<right){
10         mid = (left+right)/2;
11         if(sum[mid]>x){
12             right = mid;
13         }
14         else{
15             left = mid+1;
16         }
17     }
18     return left;
19 }
20 
21 int main(){
22     scanf("%d%d",&n,&S);
23     sum[0] = 0;
24     for(int i=1;i<=n;i++){
25         scanf("%d",&sum[i]);
26         sum[i] += sum[i-1];
27     }
28     for(int i=1;i<=n;i++){
29         int j=upper_bound(i,n+1,sum[i-1]+S); //求右端点
30         if(sum[j-1]- sum[i-1]==S){
31             nearS = S;
32             break;
33         }
34         else if(j<=n && sum[j]-sum[i-1]<nearS){
35             nearS = sum[j]- sum[i-1];
36         }
37     }
38     for(int i=1;i<=n;i++){
39         int j= upper_bound(i,n+1,sum[i-1]+nearS); //求右端点
40         if(sum[j-1]- sum[i-1] == nearS){
41             printf("%d-%d\n",i,j-1);
42         }
43     }
44 }

原则就是能查找的地方都写成二分的,注意上下界。

难点是Sum这玩意想不出来。

 

二分的题都不简单,需要特别注意下。

 

4.6 two pointers

 

B1030/A1085

思路

首先,可以很容易地获得下面这个性质:如果a[i]<=a[i]*p成立,那么对[i,j]内任意位置k,一定有a[k]<=a[i]*p也成立。这种有序序列地性质就引导我们往tow pointers思想去思考,由此可以得到以下时间复杂度为O(n)地算法:

令两个下标i,j的初值均为0,表示i、j均指向有序序列的第一个元素,并设置计数器count存放满足a[j]<=a[i]*p的最大长度。接下来让j不断增加,直到不等式a[j]<=a[i]*p恰好不成立为止(在此过程中更新count)。之后让下标i右移一位,并继续上面让j不断增加的操作,以此类推,直到j到达序列末端。这个操作的目的在于,在a[j]<=a[i]*p的条件下始终控制i和j的距离最大。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int maxn = 100010;
 5 int n,p,a[maxn];
 6 
 7 int main(){
 8     scanf("%d%d",&n,&p);
 9     for(int i=0;i<n;i++){
10         scanf("%d",&a[i]);
11     }
12     sort(a,a+n); //递增排序。
13     int count =1;
14     int i=0,j=0;
15     while(j<n && i<n){
16         while(j<n && a[j]<=(long long)a[i]*p){
17             count = max(count,j-i+1);
18             j++;
19         }
20         i++;
21     }
22     printf("%d\n",count);
23     return 0;
24 }

总之,指针不会突然往回走。

 

B1035/A1089

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int N = 111;
 5 int origin[N],tempOri[N],changed[N]; //原始数组,原始数组备份,目标数组
 6 int n;
 7 bool isSame(int A[],int B[]){
 8     for(int i=0;i<n;i++){
 9         if(A[i]!=B[i]) return false;
10     }
11     return true;
12 }
13 
14 bool showArray(int A[]){
15     for(int i=0;i<n;i++){
16         printf("%d",A[i]);
17         if(i<n-1) printf(" ");
18     }
19     printf("\n");
20 }
21 
22 bool insertSort(){
23     bool flag = false;
24     for(int i=1;i<n;i++){
25         if(i!=1 && isSame(tempOri,changed)){
26             flag = true;
27         }
28         int temp = tempOri[i],j=i;
29         while(j>0 && tempOri[j-1]>temp){
30             tempOri[j] = tempOri[j-1];
31             j--;
32         }
33         tempOri[j] = temp;
34         if(flag == true){
35             return true;
36         }
37     }
38     return false;
39 }
40 
41 void mergeSort(){
42     bool flag = false;
43     for(int step =2;step/2<=n;step*=2){
44         if(step!=2 && isSame(tempOri,changed)){
45             flag =true;
46         }
47         for(int i=0;i<n;i+=step){
48             sort(tempOri+i,tempOri+min(i+step,n));
49         }
50         if(flag == true){
51             showArray(tempOri);
52             return;
53         }
54     }
55 }
56 
57 int main(){
58     scanf("%d",&n);
59     for(int i=0;i<n;i++){
60         scanf("%d",&origin[i]);
61         tempOri[i] = origin[i];
62     }
63     for(int i=0;i<n;i++){
64         scanf("%d",&changed[i]);
65     }
66     if(insertSort()){
67         printf("Insertion Sort\n");
68         showArray(tempOri);
69     }else{
70         printf("Merge Sort\n");
71         for(int i=0;i<n;i++){
72             tempOri[i] = origin[i];
73         }
74         mergeSort();
75     }
76     return 0;
77 }

 

A1029

总算有道题能欺负下了。。。注意下两点归并的写法。

 1 #include <cstdio>
 2 typedef long long LL;
 3 int a1[200010],a2[200010],ans[400020];
 4 
 5 int main(){
 6     int n1,n2;
 7     scanf("%d",&n1);
 8     for(int i=0;i<n1;i++){
 9         scanf("%lld",&a1[i]);
10     }
11     scanf("%d",&n2);
12     for(int i=0;i<n2;i++){
13         scanf("%lld",&a2[i]);
14     }
15     int index= 0;
16     int i=0,j=0;
17     while(i<n1 && j<n2){
18         if(a1[i]<a2[j]) ans[index++] = a1[i++];
19         else ans[index++] = a2[j++];
20     }
21     while(i<n1) ans[index++] = a1[i++];
22     while(j<n2) ans[index++] = a2[j++];
23     if(n1+n2 & 1) printf("%lld",ans[(n1+n2)/2]);
24     else printf("%lld",ans[(n1+n2-1)/2]);
25 }

先用while让两个指针递增,递增完之后继续把剩下的加进去。很简单的思路,记住。

一节做一次题比较好。。好几节做感觉确实吃不消。

 

4.7 其他高效技巧与算法

 

B1045/A1101 

(1)自己尝试

 1 #include <cstdio>
 2 
 3 int ins[100010];
 4 bool left[100010]={false};
 5 bool right[100010] ={false};
 6 
 7 int main(){
 8     int n;
 9     scanf("%d",&n);
10     int maxl=-1;
11     for(int i=0;i<n;i++){
12         scanf("%d",&ins[i]);
13         if(ins[i]>maxl){
14             maxl=ins[i];
15             left[i]=true;
16         }
17     }
18     int minr=1e9+1;
19     int count =0;
20     for(int i=n-1;i>=0;i--){
21         if(ins[i]<minr){
22             minr = ins[i];
23             right[i] = true;
24             if(left[i]) count++;
25         }
26     }
27     printf("%d\n",count);
28     int outs=0;
29     for(int i=0;i<n;i++){
30         if(left[i] && right[i]){
31             printf("%d",ins[i]);
32             outs++;
33             if(outs!=count) printf(" ");
34         }
35     }
36     printf("\n");   
37 }

还是拿空间换时间。

 

B1019

(1)自己尝试

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 using namespace std;
 6 
 7 void toArray(int in,int num[]){
 8     for(int i=0;i<4;i++){
 9         num[i] = in%10;
10         in= in/10;
11     }
12 }
13 
14 int toNum(int num[]){
15     int ans=0;
16     for(int i=0;i<4;i++){
17         ans =ans*10+num[i];
18     }
19     return ans;
20 }
21 
22 bool cmp(int a,int b){
23     return a>=b;
24 }
25 
26 int main(){
27     int in;
28     scanf("%d",&in);
29     int num[5];
30     for(int i=0;i<10;i++){
31         toArray(in,num);
32         sort(num,num+4);
33         int tmp_up = toNum(num);
34         sort(num,num+4,cmp);
35         int tmp_down = toNum(num);
36         int tmp = tmp_down-tmp_up;
37         printf("%04d - %04d = %04d\n",tmp_down,tmp_up,tmp);
38         if(tmp==6174 || tmp==0) break;
39         in = tmp;
40     }
41 }

总之给数字排序是不可能排的。。

很简单的题但是写的很不熟练,莫名其妙进入瓶颈期了?

 

B1003

虽然这破题很恶心但是实际上大部分情况都是这题这样,认了吧

 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 
 5 int main(){
 6     int n;
 7     scanf("%d",&n);
 8     for(int i=0;i<n;i++){
 9         char tmp[110];
10         scanf("%s",tmp);
11         int len =strlen(tmp);
12         bool flag=true;
13         int Pnum=0,Tnum=0,Pindex=-1,Tindex=-1;
14         for(int j=0;j<len;j++){
15            if(tmp[j]!='P' && tmp[j]!='A' && tmp[j]!='T'){
16                flag =false;
17                break;
18            }
19             else if(tmp[j]=='P'){
20                 Pnum++;
21                 Pindex= j;
22             }
23             else if(tmp[j]=='T'){
24                 Tnum++;
25                 Tindex= j;
26             }
27         }
28         if(Pnum >1 || Tnum>1 || Tindex-Pindex<2){
29             flag = false;
30         }
31         else{
32             int duoA= Tindex -Pindex -2;
33             int lena = Pindex;
34             if(len-Tindex-1<lena*(duoA+1)) flag =false;
35         }
36         if(flag) printf("YES\n");
37         else printf("NO\n");
38     }
39 }

 

B1049

出现次数

 1 #include <cstdio>
 2 
 3 int main(){
 4     int n;
 5     scanf("%d",&n);
 6     long double ans=0,v;
 7     for(int i=1;i<=n;i++){
 8         scanf("%llf",&v);
 9         ans+=v*i*(n+1-i);
10     }
11     printf("%.2llf\n",ans);
12     return 0;
13 }

奇怪的坑,还有long double这种奇怪的东西。

 

A1008

(1)自己尝试

万万没想到A级居然有这么良心的题。

 1 #include <cstdio>
 2 
 3 int main(){
 4     int n;
 5     scanf("%d",&n);
 6     int tmp,last=0;
 7     int time=0;
 8     for(int i=0;i<n;i++){
 9         scanf("%d",&tmp);
10         if(tmp>last) time+=(tmp-last)*6+5;
11         else time+= (last-tmp)*4+5;
12         last= tmp;
13     }
14     printf("%d",time);
15 }

 

A1049

 1 #include <cstdio>
 2 #include <cmath>
 3 
 4 int main(){
 5     int n;
 6     scanf("%d",&n);
 7     int ans=0;
 8     int count =0;
 9     int del =0;
10     while(n>0){
11         if(n-n/10*10==0) ans+=(n/10)*pow(10,count);
12         else if(n-n/10*10==1) ans+=(n/10)*pow(10,count)+del+1;
13         else ans+=pow(10,count)+(n/10)*pow(10,count);
14         del =del + n%10*pow(10,count);
15         n/=10;
16         count++;
17     }
18     printf("%d",ans);
19 }

数学题总是会让自己觉得智商不够。这题参考下答案的写法。

分析每位上的1的个数是正确的,不过变量设的很奇怪,而且分类很奇怪,主要应该是因为1是个不上不下的数字。

 

A1081

(1)自己尝试

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 
 7 struct Fraction{
 8     LL up,down;
 9 }ins[110];
10 
11 int gcd(LL a,LL b){
12     return !b?a:gcd(b,a%b);
13 }
14 
15 Fraction huajian(Fraction in){
16     if(in.down<0){
17         in.down = -in.down;
18         in.up = -in.up;
19     }
20     if(in.up==0){
21         in.down=1;
22     }else{
23         int d = gcd(abs(in.up),abs(in.down));
24         in.down = in.down/d;
25         in.up = in.up/d;
26     }
27     return in;
28 }
29 
30 Fraction add(Fraction a,Fraction b){
31     Fraction ans;
32     ans.up = a.up*b.down +a.down*b.up;
33     ans.down = a.down*b.down;
34     ans = huajian(ans);
35     return ans;
36 }
37 
38 void printFrc(Fraction a){
39     if(a.down ==1){
40         printf("%lld",a.up);
41     }
42     else if(a.up>a.down){
43         printf("%lld %lld/%lld",a.up/a.down,a.up%a.down,a.down);
44     }
45     else{
46         printf("%lld/%lld",a.up,a.down);
47     }
48 }
49 
50 int main(){
51     int n;
52     scanf("%d",&n);
53     Fraction ans;
54     ans.up=0;
55     ans.down=1;
56     for(int i=0;i<n;i++){
57         Fraction tmp;
58         scanf("%lld/%lld",&tmp.up,&tmp.down);
59         ans = add(ans,tmp);
60     }
61     printFrc(ans);
62 }

全靠课本抬一手。注意点首先是存储分数用结构体,分数需要化简(为输出准备),分数加法的公式,分数输出的三种情况。

 

B1034/A1088

(1)自己尝试

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;

struct Fraction {
    LL up, down;
}a, b;

int gcd(LL a, LL b) {
    return !b ? a : gcd(b, a%b);
}

Fraction huajian(Fraction in) {
    if (in.down < 0) {
        in.down = -in.down;
        in.up = -in.up;
    }
    if (in.up == 0) {
        in.down = 1;
    }
    else {
        int d = gcd(abs(in.up), abs(in.down));
        in.down = in.down / d;
        in.up = in.up / d;
    }
    return in;
}

Fraction add(Fraction a, Fraction b) {
    Fraction ans;
    ans.up = a.up*b.down + a.down*b.up;
    ans.down = a.down*b.down;
    ans = huajian(ans);
    return ans;
}

Fraction jian(Fraction a, Fraction b) {
    Fraction ans;
    ans.up = a.up*b.down - a.down*b.up;
    ans.down = a.down*b.down;
    ans = huajian(ans);
    return ans;
}

Fraction times(Fraction a, Fraction b) {
    Fraction ans;
    ans.up = a.up*b.up;
    ans.down = a.down*b.down;
    ans = huajian(ans);
    return ans;
}

Fraction chu(Fraction a, Fraction b) {
    Fraction ans;
    ans.up = a.up*b.down;
    ans.down = a.down*b.up;
    ans = huajian(ans);
    return ans;
}

void printFrc(Fraction a) {
    a = huajian(a);
    if (a.up < 0) {
        printf("(");
    }
    if (a.down == 1) {
        printf("%lld", a.up);
    }
    else if (a.down == 0) {
        printf("Inf");
    }
    else if (abs(a.up) > a.down) {
        if(abs(a.up)%a.down!=0) printf("%lld %lld/%lld", a.up / a.down, abs(a.up)%a.down, a.down);
        else printf("%lld", a.up / a.down);
    }
    else {
        printf("%lld/%lld", a.up, a.down);
    }
    if (a.up < 0) {
        printf(")");
    }
}

int main() {
    scanf("%lld/%lld %lld/%lld", &a.up, &a.down, &b.up, &b.down);
    printFrc(a);
    printf(" + ");
    printFrc(b);
    printf(" = ");
    printFrc(add(a, b));
    printf("\n");
    printFrc(a);
    printf(" - ");
    printFrc(b);
    printf(" = ");
    printFrc(jian(a, b));
    printf("\n");
    printFrc(a);
    printf(" * ");
    printFrc(b);
    printf(" = ");
    printFrc(times(a, b));
    printf("\n");
    printFrc(a);
    printf(" / ");
    printFrc(b);
    printf(" = ");
    printFrc(chu(a, b));
}

长的脑阔疼,放弃思考了。

 

B1013

(1)自己尝试

 1 #include <cstdio>
 2 
 3 const int maxn = 1000010;
 4 bool nums[maxn]={0};
 5 int sushu[maxn];
 6 
 7 int main(){
 8     int m,n;
 9     scanf("%d%d",&m,&n);
10     int count=0;
11     for(int i=2;i<=maxn;i++){
12         if(nums[i]==false){
13             sushu[count++] =i;
14         }
15         for(int j=i+i;j<maxn;j+=i){
16             nums[j]=true;
17         }
18     }
19     int idx=0;
20     for(int i=m-1;i<n;i++){
21         printf("%d",sushu[i]);
22         idx++;
23         if(idx==10){
24             printf("\n");
25             idx=0;
26             
27         }
28         else if(i!=n-1) printf(" ");
29     }
30 }

不知道第10000个素数有多大,所以maxn设大一些。

 

A1015

这题先过了。

 1 #include <iostream>
 2 using namespace std;
 3 bool isPrime(int a){
 4     if(a==0||a==1) return false;
 5     for(int i=2;i*i<=a;i++){
 6         if(a%i==0) return false;
 7     }
 8     return true;
 9 }
10 int main(){
11     while(1){
12         int n,tmp,m,sum=0;
13         cin>>n;
14         if(n<0) break;
15         cin>>m;
16         tmp=n;
17         while(tmp){
18             sum = sum*m + (tmp%m);
19             tmp/=m;
20         }
21         printf("%s\n",isPrime(n)&&isPrime(sum)?"Yes":"No");
22     }
23     return 0;
24 } 

对于进制的理解:都和十进制一样,转化为10进制,最高位是进制的n次方。

 

 1 #include <cstdio>
 2 #include <cmath>
 3 typedef long long LL;
 4 const LL maxn= 100010;
 5 LL primes[maxn];
 6 LL notPrime[maxn]={0};
 7 
 8 struct factor{
 9     LL n1;
10     LL cnt;
11 }factors[30];
12 
13 void getPrimes(){
14     LL index =0;
15     for(int i=2;i<maxn;i++){
16         if(notPrime[i]==false){
17             primes[index++] = i;
18             for(int j=i+i;j<maxn;j+=i){
19                 notPrime[j] =true;
20             }
21         }
22     }
23 }
24 
25 int main(){
26     getPrimes();
27     LL n;
28     scanf("%lld",&n);
29     LL n2 = n;
30     LL max =(int)sqrt(n);
31     LL prime = 2;
32     LL index =0,id=0;
33     while(prime<=max){
34         prime = primes[index];
35         if(n%prime==0){
36             factors[id].n1 = prime;
37             factors[id].cnt = 0;
38             while(n%prime==0){
39                 factors[id].cnt++;
40                 n=n/prime;
41             }
42             id++;
43         }
44         index++;
45     }
46     
47     if(n>1){
48         factors[id].n1 = n;
49         factors[id].cnt = 1;
50         id++;
51     }
52     printf("%lld=",n2);
53     for(int i=0;i<id;i++){
54         printf("%lld",factors[i].n1);
55         if(factors[i].cnt>1) printf("^%lld",factors[i].cnt);
56         if(i!=id-1) printf("*");
57     }
58     if(n2==1) printf("1");
59 }

注意n==1时候需要特判输出1=1。


B1017

 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 struct bign{
 5     int d[1010];
 6     int len;
 7     bign(){
 8         memset(d,0,sizeof(d));
 9         len = 0;
10     }
11 };
12 
13 bign change(char in[]){
14     bign a;
15     a.len = strlen(in);
16     for(int i=0;i<a.len;i++){
17         a.d[i] = in[a.len-i-1]-'0';
18     }
19     return a;
20 }
21 
22 bign divide(bign a,int b,int &yushu){
23     bign d;
24     d.len = a.len;
25     int carry=0;
26     for(int i=a.len-1;i>=0;i--){
27         int tmp = carry*10+a.d[i];
28         d.d[i] = tmp/b;
29         carry = tmp%b;
30         if(i==0) yushu = carry;
31     }
32     if(d.d[d.len-1]==0 && d.len>=2){
33         d.len--;
34     }
35     return d;
36 }
37 
38 int main(){
39     char in[1000];
40     int b;
41     scanf("%s %d",in,&b);
42     bign a = change(in);
43     int yushu =0;
44     bign d = divide(a,b,yushu);
45     for(int i=d.len-1;i>=0;i--){
46         printf("%d",d.d[i]);
47     }
48     printf(" %d",yushu);
49 }#include <cstdio>
50 #include <cstring>
51 
52 struct bign{
53     int d[1010];
54     int len;
55     bign(){
56         memset(d,0,sizeof(d));
57         len = 0;
58     }
59 };
60 
61 bign change(char in[]){
62     bign a;
63     a.len = strlen(in);
64     for(int i=0;i<a.len;i++){
65         a.d[i] = in[a.len-i-1]-'0';
66     }
67     return a;
68 }
69 
70 bign divide(bign a,int b,int &yushu){
71     bign d;
72     d.len = a.len;
73     int carry=0;
74     for(int i=a.len-1;i>=0;i--){
75         int tmp = carry*10+a.d[i];
76         d.d[i] = tmp/b;
77         carry = tmp%b;
78         if(i==0) yushu = carry;
79     }
80     if(d.d[d.len-1]==0 && d.len>=2){
81         d.len--;
82     }
83     return d;
84 }
85 
86 int main(){
87     char in[1000];
88     int b;
89     scanf("%s %d",in,&b);
90     bign a = change(in);
91     int yushu =0;
92     bign d = divide(a,b,yushu);
93     for(int i=d.len-1;i>=0;i--){
94         printf("%d",d.d[i]);
95     }
96     printf(" %d",yushu);
97 }

 

A1047

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6 
 7 const int maxn = 40010;
 8 char stus[maxn][5];
 9 vector<int> course[maxn];
10 
11 bool cmp(int a,int b){
12     return strcmp(stus[a],stus[b])<0;
13 }
14 
15 int main(){
16     int n,k;
17     scanf("%d%d",&n,&k);
18     for(int i=0;i<n;i++){
19         int courseNum;
20         scanf("%s %d",stus[i],&courseNum);
21         for(int j=0;j<courseNum;j++){
22             int tmp;
23             scanf("%d",&tmp);
24             course[tmp].push_back(i);
25         }
26     }
27     for(int i=1;i<=k;i++){
28         printf("%d %d\n",i,course[i].size());
29         sort(course[i].begin(),course[i].end(),cmp);
30         for(int j=0;j<course[i].size();j++){
31             printf("%s\n",stus[course[i][j]]);
32         }
33     }
34 }

原来排序也可以借助外部数组,很有意思。。。然后就是vector的排序参数是头指针和末尾指针,注意写法,不能直接用名字。

 

A1063

(1)参考答案

 1 #include <cstdio>
 2 #include <set>
 3 using namespace std;
 4 const int N = 51;
 5 set<int> st[N];
 6 void compare(int x,int y){
 7     int totalNum = st[y].size(), samenum=0;
 8     for(set<int>::iterator it =st[x].begin();it!=st[x].end();it++){
 9         if(st[y].find(*it)!=st[y].end()) samenum++; //注意这个判断条件怎么写
10         else totalNum++;
11     }
12     printf("%.1f%%\n",samenum*100.0/totalNum);
13 }
14 
15 int main(){
16     int n,k,q,v,st1,st2;
17     scanf("%d",&n);
18     for(int i=1;i<=n;i++){
19         scanf("%d",&k);
20         for(int j=0;j<k;j++){
21             scanf("%d",&v);
22             st[i].insert(v);
23         }
24     }
25     scanf("%d",&q);
26     for(int i=0;i<q;i++){
27         scanf("%d%d",&st1,&st2);
28         compare(st1,st2);
29     }
30 }

这题,compare函数的写法注意一下,通过遍历一个与另外一个比,然后注意判断条件。

 

A1060

(1)自己尝试

做到21分差不多得了。看答案了。

  1 #include <cstring>
  2 #include <cstdio>
  3 char a[110], b[110];
  4 
  5 int buling(char a[], int n) {
  6     char now = a[0];
  7     int len = 0;
  8     if (a[0] != '0') {
  9         do {
 10             now = a[len];
 11             if (now == '.' || now == '\0') {
 12                 for (int i = 1; i <= n; i++) {
 13                     if (a[len + i] == '.') a[len + i] = '0';
 14                 }
 15                 break;
 16             }
 17             len++;
 18         } while (1);
 19     }
 20     else {
 21         do {
 22             now = a[len];
 23             if (now != '.' && now != '0') {
 24                 for (int i = 0; i <= n; i++) {
 25                     if (a[len + i] == '.') a[len + i] = '0';
 26                 }
 27                 len -= 2;
 28                 break;
 29             }
 30             len++;
 31         } while (1);
 32     }
 33     return len;
 34 }
 35 
 36 bool equal(char a[], char b[], int n,int begin) {
 37     for (int i = 0; i < n; i++) {
 38         if (a[i+begin] != b[i+begin]) return false;
 39     }
 40     return true;
 41 }
 42 
 43 int main() {
 44     memset(a, '.', sizeof(a));
 45     memset(b, '.', sizeof(b));
 46     int n;
 47     scanf("%d%s%s", &n, a, b);
 48     int lena = buling(a, n) ;
 49     int lenb = buling(b, n);
 50     if (a[0] != '0') {
 51         if (lena == lenb && equal(a, b, n,0)) {
 52             printf("YES 0.");
 53             for (int i = 0; i < n; i++) {
 54                 if(a[i]=='.'){
 55                     i++;
 56                     n++;
 57                 }
 58                 printf("%c", a[i]);
 59             }
 60             printf("*10^%d", lena);
 61         }
 62         else {
 63             printf("NO 0.");
 64             for (int i = 0; i < n; i++) {
 65                 if(a[i]=='.'){
 66                     i++;
 67                     n++;
 68                 }
 69                 printf("%c", a[i]);
 70             }
 71             printf("*10^%d ", lena);
 72             printf("0.");
 73             for (int i = 0; i < n; i++) {
 74                 if(a[i]=='.'){
 75                     i++;
 76                     n++;
 77                 }
 78                 printf("%c", b[i]);
 79             }
 80             printf("*10^%d", lenb);
 81         }
 82     }
 83     else {
 84         if (lena == lenb && equal(a, b, n,lena+2)) {
 85             printf("YES 0.");
 86             for (int i = 0; i < n; i++) {
 87                 printf("%c", a[lena+i+2]);
 88             }
 89             printf("*10^-%d", lena);
 90         }
 91         else {
 92             printf("NO 0.");
 93             for (int i = 0; i < n; i++) {
 94                 printf("%c", a[lena + i + 2]);
 95             }
 96             printf("*10^-%d ", lena);
 97             printf("0.");
 98             for (int i = 0; i < n; i++) {
 99                 printf("%c", b[lenb + i + 2]);
100             }
101             printf("*10^-%d", lenb);
102         }
103     }
104 }

(2)参考答案

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 int n;
 5 string deal(string s,int& e){
 6     int k=0; //s的下标
 7     while(s.length()>0 && s[0]=='0'){
 8         s.erase(s.begin());
 9     }
10     if(s[0]=='.'){
11         s.erase(s.begin());
12         while(s.length()>0 && s[0]=='0'){
13             s.erase(s.begin());
14             e--;
15         }
16     }else{
17         while(k<s.length() && s[k]!='.'){
18             k++;
19             e++;
20         }
21     
22     if(k<s.length()){
23         s.erase(s.begin()+k);
24     }
25     }
26     if(s.length()==0){
27         e = 0;
28     }
29     int num=0;
30     k=0;
31     string res;
32     while(num<n){
33         if(k<s.length()) res+=s[k++];
34         else res += '0'; //否则res末尾添加0
35         num++;
36     }
37     return res;
38 }
39 
40 int main(){
41     string s1,s2,s3,s4;
42     cin >> n >> s1>>s2;
43     int e1=0,e2=0;
44     s3 =deal(s1,e1);
45     s4 = deal(s2,e2);
46     if(s3==s4 && e1 ==e2){
47         cout <<"YES 0." << s3 << "*10^" << e1 <<endl;
48     }
49     else{
50         cout << "NO 0."<< s3 <<"*10^" << e1 << " 0." << s4 <<"*10^"<<e2<<endl;
51     }
52 }

 

B1044/A1100

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <string>
 4 #include <map>
 5 using namespace std;
 6 
 7 string unitDigit[13] = {"tret","jan","feb","mar","apr","may","jun","jly","aug","sep","oct","nov","dec"};
 8 string tenDigit[13] = {"tret","tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mer","jou"};
 9 string numToStr[170];
10 map <string,int> strToNum;
11 
12 void init(){
13     for(int i=0;i<13;i++){
14         numToStr[i] = unitDigit[i];
15         strToNum[unitDigit[i]] =i;
16         numToStr[i*13] = tenDigit[i];
17         strToNum[tenDigit[i]] = i*13;
18     }
19     for(int i=1;i<13;i++){
20         //这里很巧妙地避开了带0的。
21         for(int j=1;j<13;j++){
22             string str = tenDigit[i] + " " +unitDigit[j];
23             numToStr[i*13+j] =str;
24             strToNum[str] = i*13+j;
25         }
26     }
27 }
28 
29 int main(){
30     init();
31     int T;
32     scanf("%d%c",&T); //查询个数
33     while(T--){
34         string str;
35         getline(cin,str);
36         if(str[0]>='0' && str[0]<='9'){
37             int num=0;
38             for(int i=0;i<str.length();i++){
39                 num=num*10 +str[i]-'0';
40             }
41             cout << numToStr[num] << endl;
42         }
43         else{
44             cout << strToNum[str] << endl;
45         }
46     }
47     return 0;
48 }

注意用getline之前吸收那个char。

 

A1054

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <map>
 4 using namespace std;
 5 map<int,int> colors;
 6 
 7 int main(){
 8     int m,n;
 9     scanf("%d%d",&m,&n);
10     for(int i=0;i<m;i++){
11         for(int j=0;j<n;j++){
12             int tmp;
13             scanf("%d",&tmp);
14             colors[tmp]++;
15             if(colors[tmp]>n*m/2) printf("%d",tmp);
16         }
17     }
18 }

过于令人感动,终于有白给的题了。

if(colors.find(col)!=count.end()) count[col]++;

else counlt[col]=1;

map的初始化写法。

 

 

A1071

 1 #include <cstdio>
 2 #include <string>
 3 #include <map>
 4 #include <iostream>
 5 using namespace std;
 6 
 7 map<string, int> mp;
 8 
 9 char judge(char a) {
10     if (a >= '1' && a <= '9') return a;
11     else if (a >= 'a' && a <= 'z') return a;
12     else if (a >= 'A' && a <= 'Z') return a - 'A' + 'a';
13     else return -1;
14 }
15 
16 string findMax(map<string, int> mp, int &idx) {
17     string ans;
18     for (map<string, int>::iterator it = mp.begin(); it != mp.end(); it++) {
19         if (it->second > idx) {
20             idx = it->second;
21             ans = it->first;
22         }
23     }
24     return ans;
25 }
26 
27 int main() {
28     string in;
29     getline(cin, in);
30     int len = in.length();
31     string tmp = "";
32     for (int i = 0; i < len; i++) {
33         
34         char in1 = judge(in[i]);
35         if (in1 != -1) {
36             tmp.push_back(in1);
37         }
38         else {
39             if(tmp!=""){
40             if (mp.find(tmp) == mp.end()) mp[tmp] = 1;
41             else mp[tmp]++;
42             }
43             tmp = "";
44         }
45     }
46     int idx = 0;
47     string ans = findMax(mp, idx);
48     if(mp.size()!=0){
49     cout << ans << " " << idx << endl;
50     }
51     else{
52         cout<< in << " " << 1 << endl;
53     }
54 }

注意一下特殊情况(一个单词)的处理。

 

A1071

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <map>
 4 #include <set>
 5 #include <string>
 6 using namespace std;
 7 map<string, set<int>> mpTitle, mpAuthor, mpKey, mpPub, mpYear;
 8 
 9 void query(map<string, set<int>>& mp, string& str) {
10     if (mp.find(str) == mp.end()) printf("Not Found\n");
11     else {
12         for (set<int>::iterator it = mp[str].begin(); it != mp[str].end(); it++) {
13             printf("%07d\n", *it);
14         }
15     }
16 }
17 
18 int main() {
19     int n, m, id, type;
20     string title, author, key, pub, year;
21     scanf("%d", &n);
22     for (int i = 0; i < n; i++) {
23         scanf("%d", &id);
24         char c = getchar();
25         getline(cin, title);
26         mpTitle[title].insert(id);
27         getline(cin, author);
28         mpAuthor[author].insert(id);
29         while (cin >> key) { //注意学习下这个写法
30             mpKey[key].insert(id);
31             c = getchar();
32             if (c == '\n') break;
33         }
34         getline(cin, pub);
35         mpPub[pub].insert(id);
36         getline(cin, year);
37         mpYear[year].insert(id);
38     }
39     string temp;
40     scanf("%d", &m);
41     for (int i = 0; i < m; i++) {
42         scanf("%d: ", &type);
43         getline(cin, temp);
44         cout << type << ": " << temp << endl;
45         if (type == 1) query(mpTitle, temp);
46         else if (type == 2) query(mpAuthor, temp);
47         else if (type == 3) query(mpKey, temp);
48         else if (type == 4) query(mpPub, temp);
49         else query(mpYear, temp);
50     }
51 }

这是一道很常用的题,注意如果有多个关键词,每个都建立一个映射数组即可。

同时如果把查询提炼成一个函数,那么一定对参数使用引用,否则最后一组数据会超时。由此可见,字符串及map的参数传递速度较慢,如果需要作为函数的参数的话,需要尽可能加上引用。

 

A1051

(1)自己尝试

 1 #include <stack>
 2 #include <cstdio>
 3 #include <iostream>
 4 using namespace std;
 5 
 6 
 7 int main() {
 8     int m, n, k;
 9     scanf("%d%d%d", &m, &n, &k);
10     for (int i = 0; i < k; i++) {
11         int now = 1;
12         stack<int> stk;
13         bool flag = true;
14         for (int j = 0; j < n; j++) {
15             int tmp;
16             scanf("%d", &tmp); //记录下一个输入
17             if (stk.empty() || stk.top() != tmp) {
18                 if (now <= tmp) {
19                     while (now <= tmp) {
20                         stk.push(now); //加到tmp-1
21                         now++;  //tmp结束
22                     }
23                     if (stk.size() > m) {
24                         flag = false;
25 
26                     }
27                     stk.pop();
28                 }
29                 else {
30                     flag = false;
31                 }
32             }
33             else {
34                 stk.pop();
35             }
36             //这时进入下一循环。
37         }
38         if (flag == true) printf("YES\n");
39         else printf("NO\n");
40     }
41 }

虽然不知道怎么对的但是debug大法好。根据答案分析一下。

 

posted @ 2021-03-10 20:53  魂淡菌  阅读(69)  评论(0)    收藏  举报