【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大法好。根据答案分析一下。

浙公网安备 33010602011771号