2020 CCPC Wannafly Winter Camp Day1
https://ac.nowcoder.com/acm/contest/3979
B,
密码学
题意是每行给你一个x,y表示第x个字符串对第y个字符串加密
加密的方式是将字符换成数字,然后x的字符加上y的字符模52再变回字符。如果x小于y,则你的x将重复直至大于等于y
模拟,不过你得倒序模拟
#include<bits/stdc++.h> using namespace std; string s[1001]; int x[1001],y[1001]; int getnum(char c) { if(c>='a'&&c<='z') return c-'a'; else return c-'A'+26; } char getword(int x) { if(x<26) return 'a'+x; else return x-26+'A'; } int main() { // cin>>s[1]>>s[2]; // cout<<s[1]<<s[2]<<endl; int n,m; cin>>n>>m; for(int i=1;i<=m;i++)cin>>x[i]>>y[i]; for(int i=1;i<=n;i++)cin>>s[i]; for(int i=m;i>=1;i--){ int l=x[i],r=y[i]; int sz1=s[l].size(); int sz2=s[r].size(); for(int j=0;j<sz2;j++){ int t=getnum(s[l][j%sz1]),t2=getnum(s[r][j]); s[r][j]=getword((t2-t+52)%52); } } for(int i=1;i<=n;i++) cout<<s[i]<<endl; }
H
首先我们得知的是gcd(k,y)的值必须的是唯一,你不能出现gcd(y,其他数)==gcd(y,k)这样就不能用来判断k是不是他给的x;
好了已经知道gcd(k,y)是唯一的,接下来就是其他的东西了
既然是唯一的就得避免gcd出来的值是1,因为这样的话当k是质数,y可以是1,y是质数也可以,不满足题目;
故你的y必须是k的倍数,这样当k是质数时也不出问题,所以ans=k;(基础的一倍)
接下来就是y必须是p的倍数,(p为素数且pk<=n)因为p是素数所以在gcd时不影响他的结果,这样就会导致A给了B是k,给你pk,当时通过gcd你无法正确判断了(gcd(y,k)=gcd(y,pk))
所以我们需要将素数部分全部乘起来再乘以ans,
由于特殊情况当500内的素数全部相乘,数字会超大
我们用大数相乘
#include<bits/stdc++.h> using namespace std; int p[505], n, m, i, j, t, k, l, a[2000]; bool vis[505]; void mul(int n) { for(int i=0;i<1000;i++) a[i]*=n; for(int i=0;i<1000;i++){ a[i+1]+=a[i]/10000; a[i]=a[i]%10000; } } void prin() { int i=1000; while(i>=0&&!a[i]) i--; printf("%d",a[i--]); while(i>=0) printf("%04d",a[i--]); } int main() { //freopen("in.txt", "r", stdin); n = 500; for (i = 2; i <= n; i++) { //线筛 if (!vis[i]) p[m++] = i; for (j = 0; j < m && i*p[j] <= n; j++) { vis[i*p[j]] = 1; if (i%p[j] == 0) break; } } scanf("%d", &t); while (t--) { scanf("%d%d", &n, &k); memset(a, 0, sizeof(a)); a[0] = l = 1; for (i = 0; i < m && k*p[i] <= n; i++) mul(p[i]); mul(k); // for (i = l - 1; ~i; i--) printf("%d", a[i]); prin(); puts(""); } }
第k大数查询
通过二分这个值
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #define LL long long using namespace std; const int maxn = 1e5 + 5; LL a[maxn], b[maxn]; LL n, m, k; bool che(LL mid) { LL num = 0; for (int i = 1; i <= m; i++) { if (b[i] == 0) num += mid < 0 ? n : 0; if (b[i] < 0) num += lower_bound(a + 1, a + n + 1, ceil((double)mid / b[i])) - (a + 1); if (b[i] > 0) num += n - ((upper_bound(a + 1, a + n + 1, floor((double)mid / b[i]))) - (a + 1)); } return num <= k; } int main() { cin >> n >> m >> k; k--; for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); for (int i = 1; i <= m; i++) scanf("%lld", &b[i]); sort(a + 1, a + n + 1); sort(b + 1, b + m + 1); LL l = -1e13, r = 1e13; while (l + 1 < r) { LL mid = (l + r) >> 1; if (che(mid))r = mid; else l = mid; } cout << r << endl; return 0; }