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;
}

  

posted on 2020-02-02 12:13  师姐的迷弟  阅读(181)  评论(0编辑  收藏  举报

导航