夜深人静写题解--杭电第五场
1001 fraction
题意:求出最小的B使得A==BX(MOD P) 0<A<B。
思路:
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 void f(ll lup,ll ldown,ll rup,ll rdown,ll &x,ll &y) 5 { 6 ll mm=lup/ldown+1; 7 if(mm<=rup/rdown) 8 { 9 x=mm; 10 y=1; 11 return ; 12 } 13 mm--; 14 lup-=mm*ldown; 15 rup-=mm*rdown; 16 f(rdown,rup,ldown,lup,y,x); 17 x+=(mm)*y; 18 return ; 19 } 20 int main() 21 { 22 int t; 23 scanf("%d",&t); 24 while(t--) 25 { 26 ll p,x,a,b; 27 scanf("%lld%lld",&p,&x); 28 f(p,x,p,x-1,a,b); 29 ll z=x*a-b*p; 30 //printf("%lld %lld\n",a,b); 31 printf("%lld/%lld\n",z,a); 32 } 33 34 }
1002 three arrays
题意:对于两个数组A和B,任意安排A中的顺序,任意安排B中的顺序,数组C为Ai ^ Bi 的值,求出使得C字典序最小的情况,输出C数组。
思路:由于异或的性质,我们就尽可能的将数完备的“匹配“,贪心的对高位匹配,两个数字相异或,高位如果尽可能的消去,得到的结果就会越小,所以贪心的求解,由于数据范围的局限性,我们需要对数组A和B分别建立一个01字典树,每次贪心的在字典树上进行匹配,然后将其保存,考虑到我们求解过程中并不一定按照顺序求解,所以为保证字典序最小,需要将C数组进行排序后输出。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+7; 4 struct node 5 { 6 int s[2]; 7 bool en; 8 int si; 9 }; 10 int ans[maxn]; 11 struct trie 12 { 13 node a[31*maxn]; 14 int num; 15 void init(int n) 16 { 17 memset(a,0,sizeof(node)*(n*31+1)); 18 num=1; 19 } 20 void inser(int x) 21 { 22 int st=1; 23 for(int i=30;i>=0;i--) 24 { 25 ++a[st].si; 26 int q=(x>>i)&1; 27 if(a[st].s[q]==0) 28 { 29 a[st].s[q]=++num; 30 st=num; 31 } 32 else 33 { 34 st=a[st].s[q]; 35 } 36 } 37 ++a[st].si; 38 a[st].en=1; 39 } 40 41 }trie1,trie2; 42 43 int main() 44 { 45 int t; 46 scanf("%d",&t); 47 while(t--) 48 { 49 int n; 50 scanf("%d",&n); 51 trie1.init(n);trie2.init(n); 52 for(int i=1;i<=n;i++) 53 { 54 int x; 55 scanf("%d",&x); 56 trie1.inser(x); 57 } 58 for(int i=1;i<=n;i++) 59 { 60 int x; 61 scanf("%d",&x); 62 trie2.inser(x); 63 } 64 for(int i=1;i<=n;i++) 65 { 66 int ans1=0; 67 int l1=1; 68 int l2=1; 69 while(!trie1.a[l1].en&&!trie2.a[l2].en) 70 { 71 --trie1.a[l1].si;--trie2.a[l2].si; 72 ans1<<=1; 73 int t10=trie1.a[trie1.a[l1].s[0]].si>0; 74 int t11=trie1.a[trie1.a[l1].s[1]].si>0; 75 int t20=trie2.a[trie2.a[l2].s[0]].si>0; 76 int t21=trie2.a[trie2.a[l2].s[1]].si>0; 77 if(t11&&t21) 78 { 79 l1=trie1.a[l1].s[1]; 80 l2=trie2.a[l2].s[1]; 81 } 82 else if(t10&&t20) 83 { 84 l1=trie1.a[l1].s[0]; 85 l2=trie2.a[l2].s[0]; 86 } 87 else if(t11&&t20) 88 { 89 l1=trie1.a[l1].s[1]; 90 l2=trie2.a[l2].s[0]; 91 ans1++; 92 } 93 else if(t10&&t21) 94 { 95 l1=trie1.a[l1].s[0]; 96 l2=trie2.a[l2].s[1]; 97 ans1++; 98 } 99 } 100 --trie1.a[l1].si; 101 --trie2.a[l2].si; 102 ans[i]=ans1; 103 } 104 sort(ans+1,ans+1+n); 105 for(int i=1;i<=n;i++) 106 { 107 printf("%d",ans[i]); 108 if(i!=n) 109 { 110 printf(" "); 111 } 112 } 113 printf("\n"); 114 } 115 }
1004 equation
题意:求解满足∑|ai⋅x+bi|=C的所有x值,没有则输出-1
思路:考虑到一次函数y=ax+b具有可加性,y=|ai⋅x+bi|是将其位于x轴下面的图像翻转到上方,所以我们对于每个翻转点进行枚举,枚举在每个区间内函数的叠加情况,由于其处理具有后效性,所以我们可以对其在翻转点排序之后进行前缀和的处理,可以O(1)的算出贡献情况,对当前一次函数y=kx+b与y=c进行交点求解,判断坐标是否满足要求,满足加入答案。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+7; 4 const double eps=1e-8; 5 struct node 6 { 7 int a; 8 int b; 9 } bos[maxn],ans[maxn]; 10 bool cmp(node x,node y) 11 { 12 return (-1.0*x.b/x.a)<(-1.0*y.b/y.a); 13 } 14 bool cmp2(node x,node y) 15 { 16 return x.b/x.a<y.b/y.a; 17 } 18 long long int sum[maxn],sum1[maxn]; 19 int main() 20 { 21 int t; 22 scanf("%d",&t); 23 while(t--) 24 { 25 int n,c; 26 scanf("%d%d",&n,&c); 27 for(int i=1; i<=n; i++) 28 { 29 scanf("%d%d",&bos[i].a,&bos[i].b); 30 } 31 sort(bos+1,bos+n+1,cmp); 32 sum[0]=0; 33 for(int i=1; i<=n; i++) 34 { 35 sum[i]=sum[i-1]-bos[i].a; 36 sum1[i]=sum1[i-1]-bos[i].b; 37 } 38 int fi=0; 39 long long int to=sum1[n]-c; 40 to=-to; 41 long long int bi=sum[n]; 42 int temp=0; 43 if(bi==0) 44 { 45 if(to==0) 46 { 47 fi=1; 48 } 49 } 50 else 51 { 52 if((1.0*to)/bi<=(-1.0*bos[1].b)/bos[1].a||abs((1.0*to)/bi-(-1.0*bos[1].b)/bos[1].a)<=eps) 53 { 54 ans[temp].b=to; 55 ans[temp].a=bi; 56 temp++; 57 } 58 } 59 long long int hi=0; 60 long long int low=0; 61 for(int i=1; i<=n-1; i++) 62 { 63 hi+=bos[i].b; 64 low+=bos[i].a; 65 to=sum1[n]-(sum1[i])+hi-c; 66 to=-to; 67 bi=sum[n]-(sum[i])+low; 68 //printf("to=%lld bi=%lld\n",sum1[n]-(sum1[i]),bi); 69 if(bi==0) 70 { 71 if(to==0) 72 { 73 fi=1; 74 } 75 } 76 else 77 { 78 if(((((1.0*to)/bi)>=((-1.0*bos[i].b)/bos[i].a))||abs(((1.0*to)/bi)-((-1.0*bos[i].b)/bos[i].a))<=eps)&&(((1.0*to)/bi<=((-1.0*bos[i+1].b)/bos[i+1].a))|| 79 abs((1.0*to)/bi-((-1.0*bos[i+1].b)/bos[i+1].a))<=eps)) 80 { 81 //printf(" ?? %d %d\n",bos[i].b,bos[i].a); 82 ans[temp].b=to; 83 ans[temp].a=bi; 84 temp++; 85 } 86 } 87 } 88 hi+=bos[n].b; 89 low+=bos[n].a; 90 to=hi-c; 91 to=-to; 92 bi=low; 93 //printf("to=%lld bi=%lld\n",to,bi); 94 if(bi==0) 95 { 96 if(to==0) 97 { 98 fi=1; 99 } 100 } 101 else 102 { 103 if((1.0*to)/bi>=(-1.0*bos[n].b)/bos[n].a||abs((1.0*to)/bi-(-1.0*bos[n].b)/bos[n].a)<=eps) 104 { 105 ans[temp].b=to; 106 ans[temp].a=bi; 107 temp++; 108 } 109 } 110 if(fi==1) 111 { 112 printf("-1\n"); 113 } 114 else 115 { 116 //printf("%d",temp); 117 sort(ans,ans+temp,cmp2); 118 int jishu=0; 119 for(int i=0; i<temp; i++) 120 { 121 int gcd=__gcd(abs(ans[i].a),abs(ans[i].b)); 122 //printf("%d ++ \n",gcd); 123 ans[i].a/=gcd; 124 ans[i].b/=gcd; 125 if(ans[i].a<0) 126 { 127 ans[i].a=-ans[i].a; 128 ans[i].b=-ans[i].b; 129 } 130 if(i-1>=0&&ans[i].a==ans[i-1].a&&ans[i].b==ans[i-1].b) 131 { 132 133 } 134 else jishu++; 135 // printf(" %d/%d",ans[i].b,ans[i].a); 136 } 137 printf("%d",jishu); 138 for(int i=0; i<temp; i++) 139 { 140 int gcd=__gcd(abs(ans[i].a),abs(ans[i].b)); 141 //printf("%d ++ \n",gcd); 142 ans[i].a/=gcd; 143 ans[i].b/=gcd; 144 if(ans[i].a<0) 145 { 146 ans[i].a=-ans[i].a; 147 ans[i].b=-ans[i].b; 148 } 149 if(ans[i].a==ans[i-1].a&&ans[i].b==ans[i-1].b) 150 { 151 152 } 153 else 154 printf(" %d/%d",ans[i].b,ans[i].a); 155 } 156 printf("\n"); 157 } 158 } 159 }
1005 permutation 1
题意:给出数组A,数组B为A中连续性两项的差值,Bi=Ai-A(i-1),求出B第k个字典序大的序列,数组长度小于20,k<10000
思路:考虑到K的范围,当N<=8时直接进行全排列求解,当N>8时,分开进行讨论,考虑到8!为40320,则可以知道N的前几位是固定的,对于后面的跑个全排列就行。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+7; 4 int b[40]; 5 int ans[50005][40]; 6 int ans1[50005][40]; 7 struct node 8 { 9 string x; 10 int pos; 11 } a[50005],q[50005]; 12 bool cmp(node a,node b) 13 { 14 return a.x<b.x; 15 } 16 int main() 17 { 18 int t; 19 for(int i=1; i<=8; i++) 20 { 21 b[i]=i; 22 } 23 b[0]=0; 24 int temp=0; 25 do 26 { 27 q[temp].x=""; 28 for(int i=1; i<=8; i++) 29 { 30 ans1[temp][i]=b[i]; 31 } 32 for(int i=1; i<=8; i++) 33 { 34 q[temp].x+=char(b[i]-b[i-1]+'0'); 35 q[temp].x+='|'; 36 } 37 q[temp].pos=temp; 38 temp++; 39 } 40 while(next_permutation(b+1,b+8+1)); 41 sort(q,q+temp,cmp); 42 scanf("%d",&t); 43 while(t--) 44 { 45 int n,k; 46 scanf("%d%d",&n,&k); 47 for(int i=1; i<=n; i++) 48 { 49 b[i]=i; 50 } 51 if(n<9) 52 { 53 temp=0; 54 do 55 { 56 a[temp].x=""; 57 for(int i=1; i<=n; i++) 58 { 59 ans[temp][i]=b[i]; 60 } 61 for(int i=2; i<=n; i++) 62 { 63 a[temp].x+=char(b[i]-b[i-1]+'0'); 64 a[temp].x+='|'; 65 } 66 a[temp].pos=temp; 67 temp++; 68 } 69 while(next_permutation(b+1,b+n+1)); 70 sort(a,a+temp,cmp); 71 for(int j=1; j<=n; j++) 72 { 73 printf("%d",ans[a[k-1].pos][j]); 74 if(j!=n) 75 { 76 printf(" "); 77 } 78 } 79 printf("\n"); 80 } 81 else if(n==9) 82 { 83 if(k<=5040) 84 { 85 b[1]=2; 86 b[2]=3; 87 b[3]=4; 88 b[4]=5; 89 b[5]=6; 90 b[6]=7; 91 b[7]=8; 92 b[0]=1; 93 temp=0; 94 do 95 { 96 a[temp].x=""; 97 for(int i=1; i<=7; i++) 98 { 99 ans[temp][i]=b[i]; 100 } 101 for(int i=1; i<=7; i++) 102 { 103 a[temp].x+=char(b[i]-b[i-1]+'0'); 104 a[temp].x+='|'; 105 } 106 a[temp].pos=temp; 107 temp++; 108 } 109 while(next_permutation(b+1,b+7+1)); 110 sort(a,a+temp,cmp); 111 printf("9 1 "); 112 for(int j=1; j<=7; j++) 113 { 114 printf("%d",ans[a[k-1].pos][j]); 115 if(j!=7) 116 { 117 printf(" "); 118 } 119 } 120 printf("\n"); 121 } 122 else 123 { 124 b[1]=2; 125 b[2]=3; 126 b[3]=4; 127 b[4]=5; 128 b[5]=6; 129 b[6]=7; 130 b[7]=9; 131 b[0]=1; 132 temp=0; 133 do 134 { 135 a[temp].x=""; 136 for(int i=1; i<=7; i++) 137 { 138 ans[temp][i]=b[i]; 139 } 140 for(int i=1; i<=7; i++) 141 { 142 a[temp].x+=char(b[i]-b[i-1]+'0'); 143 a[temp].x+='|'; 144 } 145 a[temp].pos=temp; 146 temp++; 147 } 148 while(next_permutation(b+1,b+7+1)); 149 int ff=temp; 150 b[1]=1; 151 b[2]=3; 152 b[3]=4; 153 b[4]=5; 154 b[5]=6; 155 b[6]=7; 156 b[7]=8; 157 b[0]=2; 158 do 159 { 160 a[temp].x=""; 161 for(int i=1; i<=7; i++) 162 { 163 ans[temp][i]=b[i]; 164 } 165 for(int i=1; i<=7; i++) 166 { 167 a[temp].x+=char(b[i]-b[i-1]+'0'); 168 a[temp].x+='|'; 169 } 170 a[temp].pos=temp; 171 temp++; 172 } 173 while(next_permutation(b+1,b+7+1)); 174 sort(a,a+temp,cmp); 175 if(a[k-1].pos<ff) 176 { 177 printf("8 1 "); 178 } 179 else 180 { 181 printf("9 2 "); 182 } 183 for(int j=1; j<=7; j++) 184 { 185 printf("%d",ans[a[k-1-5040].pos][j]); 186 if(j!=7) 187 { 188 printf(" "); 189 } 190 } 191 printf("\n"); 192 } 193 } 194 else 195 { 196 printf("%d",n); 197 for(int i=1; i<=n-9; i++) 198 { 199 printf(" %d",i); 200 } 201 for(int j=1; j<=8; j++) 202 { 203 printf(" %d",ans1[q[k-1].pos][j]+n-9); 204 } 205 printf("\n"); 206 } 207 } 208 }
1006 string matching
思路:扩展kmp裸题
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+7; 4 char a[maxn]; 5 int nex[maxn]; 6 int jishu[maxn]; 7 void pre_kmp(char x[],int m) 8 { 9 nex[0]=m; 10 int j=0; 11 while(j+1<m&&x[j]==x[j+1])j++; 12 nex[1]=j; 13 int k=1; 14 for(int i=2; i<m; i++) 15 { 16 int p=nex[k]+k-1; 17 int l=nex[i-k]; 18 if(i+l<p+1)nex[i]=l; 19 else 20 { 21 j=max(0,p-i+1); 22 while(i+j<m&&x[i+j]==x[j])j++; 23 nex[i]=j; 24 k=i; 25 } 26 } 27 } 28 int main() 29 { 30 int t; 31 scanf("%d",&t); 32 while(t--) 33 { 34 scanf("%s",a); 35 int len=strlen(a); 36 pre_kmp(a,len); 37 long long int ans=0; 38 for(int i=1; i<len; i++) 39 { 40 ans+=nex[i]; 41 if(nex[i]!=len-i) 42 { 43 ans++; 44 } 45 } 46 printf("%lld\n",ans); 47 } 48 }
1007 permutation 2
题意:你有三个正整数 n,x ,y。请计算一下排列的数量1 ~ N 满足以下条件:
1.p1= x
2.pn= y
3.abs(pi-p(i-1))<=2
思路:打表找规律
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const long long int mod=998244353; 4 const int maxn=1e5+7; 5 long long int a[maxn]; 6 long long int ans[maxn]; 7 int main() 8 { 9 int t; 10 scanf("%d",&t); 11 a[1]=1,a[2]=1,a[3]=1; 12 for(int i=4;i<=maxn;i++) 13 a[i]=(a[i-1]+a[i-3])%mod; 14 while(t--) 15 { 16 int n,x,y; 17 scanf("%d%d%d",&n,&x,&y); 18 if(x==1&&y==n) 19 { 20 printf("%lld\n",a[y]); 21 } 22 else if(x!=1&&y!=n) 23 { 24 printf("%lld\n",a[y-x-1]); 25 } 26 else printf("%lld\n",a[y-x]); 27 } 28 }