CCPC-Wannafly Winter Camp Day 1

B. 密码学

题意:

告诉你关于字符串加密的方法,然后给你一些加密操作和加密后的字符串,让你求原来的串

思路:

知道被加密后的串与加密字符可以向前推出被加密之前的串,不断向前模拟即可

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
 using namespace std;
 const int maxn=1020;
char s[maxn][105];
 int b[maxn][105];
 struct node{
     int x,y;
 }a[maxn];
 int n,m,len[maxn],tem[105];
void repair(int x,int y) {
     for(int i=0;i<len[y];i++) tem[i]=b[x][(i%len[x])];
    for(int i=0;i<len[y];i++) b[y][i] = (b[y][i]-tem[i]+52) % 52;
}

int main() {
    cin>>n>>m;
    for(int i=m;i>=1;i--) cin>>a[i].x>>a[i].y;
     for(int i=1;i<=n;i++){
         cin>>s[i];
         len[i]=strlen(s[i]);
     }
    for(int i=1;i<=n;i++){
        for(int j=0;j<len[i];j++){
            if(s[i][j]>='a'&&s[i][j]<='z')
                b[i][j]=s[i][j]-'a';
            else if(s[i][j]>='A'&&s[i][j]<='Z')
                b[i][j]=s[i][j]-'A'+26;
        }
    }
     for(int i=1;i<=m;i++)repair(a[i].x,a[i].y);
    for(int i=1;i<=n;i++){
        for(int j=0;j<len[i];j++){
            if(b[i][j]>=0&&b[i][j]<=25)
                s[i][j]=b[i][j]+'a';
            else if(b[i][j]>=26&&b[i][j]<=51)
                s[i][j]=(b[i][j]-26)+'A';
        }
    }
    for(int i=1;i<=n;i++)
        cout<<s[i]<<endl;
    return 0;    
  } 

H. 最大公约数

思路:

从k开始累乘k的倍数并且为素数的数

记得要用大数!!没发现爆了WA了好几发

#include<bits/stdc++.h>
using namespace std;

int t,n,k;
string ans,str;
void initial(string &a, string &b){
    while (a.size()<b.size())a = '0' + a;
    while (b.size()<a.size())b = '0' + b;
}
//打印
void print(string &a, string &b){
    cout << a << endl;
    cout << b << endl;
}
//找出最大的字符串
void findMax(string &a, string &b){
    string tmp;
    if (a<b){
        tmp = b;
        b = a;
        a = tmp;
    }
}
//删除第一个字符'0'
bool del(string &a){
    if (a[0] == '0'){
        a.erase(0, 1);
        return true;
    }
    else
        return false;
}
//删除前面所有的 0
void delAllZroe(string &a){
    while (del(a)){
        del(a);
    };
}
//大数加法
string bigItergeAdd(string a, string b){
    initial(a, b);
    a = '0' + a;
    b = '0' + b;
    for (int i = a.size() - 1; i >= 0; i--){
        int num1 = a[i] - '0';
        int num2 = b[i] - '0';
        if (num1 + num2>9){
            a[i - 1] = a[i - 1] - '0' + 1 + '0';
            a[i] = (num1 + num2) - 10 + '0';
        }
        else{
            a[i] = (num1 + num2) + '0';
        }
    }
    del(a);
    //    cout<<a<<endl;
    return a;
}
//大数减法
string bigItergeSub(string a, string b){
    initial(a, b);
    findMax(a, b);
    for (int i = a.size() - 1; i >= 0; i--){
        int num1 = a[i] - '0';
        int num2 = b[i] - '0';
        if (num1<num2){
            a[i - 1] = a[i - 1] - '0' - 1 + '0';
            a[i] = (num1 + 10 - num2) + '0';
        }
        else{
            a[i] = (num1 - num2) + '0';
        }
    }
    del(a);
    //    cout<<a<<endl;
    return a;
}
//大数乘法(大数加法实现)
string bigItergeMul(string a, string b){
    delAllZroe(a);
    delAllZroe(b);
    initial(a, b);
    findMax(a, b);
    string res = "0";
    int count = 0;
    delAllZroe(b);
    for (int i = b.size() - 1; i >= 0; i--){
        int num1 = b[i] - '0';
        if (i != b.size() - 1)        a = a + '0';
        for (int i = 1; i <= num1; i++){
            res = bigItergeAdd(res, a);
        }
    }
    delAllZroe(res);
    return res;
}

bool prime(int x)
{
    for(int i=2;i<=sqrt(x);i++)
    {
        if(x%i==0) return false;
    }
    return true;
 } 
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        int temp=k;
        ans="";
        while(temp)
        {
            ans+=temp%10+'0';
            temp/=10;
        }
        reverse(ans.begin(),ans.end());
        for(int i=2;i*k<=n;i++)
        {
            if(prime(i))
            {
                str="";
                temp=i;
                while(temp)
                {
                   str+=temp%10+'0';
                   temp/=10;
                }
              //  cout<<str<<endl;
                reverse(str.begin(),str.end());
                ans=bigItergeMul(ans,str);
            }
        }
        
        cout<<ans<<endl;
    }        
}

F. 乘法

题意:

给你一个由两个数组a,b相乘构成的矩阵C,求矩阵中第K大的数

思路:

先将b数组排序,之后在从-1e12到1e12中二分答案,特别要注意a数组中小于0时在b数组中二分的情况,与a元素等于0时的情况

#include<iostream>
#include<algorithm>
#include<cstdio>
const int maxn=1e5+10;
using namespace std;
typedef long long ll;
 ll a[maxn],b[maxn];
 int n,m;
 ll ans,k;
 ll find(ll temp,ll x)
 {
     int l=1,r=m,mid,ret;
         if(x>0){
             ret=m+1;
             while(l<=r){
                 mid=(l+r)>>1;
                 if(b[mid]*x>=temp)    r=(ret=mid)-1;
                 else    l=mid+1;
             }
             return m-ret+1;
         }
        else if(x<0){
            ret=0;
            while(l<=r){
                mid=(l+r)>>1;
                if(b[mid]*x>=temp)    l=(ret=mid)+1;
                else r=mid+1;
            }
            return ret;
        }
}
 ll  judge(ll mid)
 {
     ll cnt=0;
     for(int i=1;i<=n;i++){
         if(a[i]==0)
             cnt+=(0>=mid)*m;
         else
             cnt+=find(mid,a[i]);
     }
    return cnt;
 }
 int main()
 {
     scanf("%d%d%lld",&n,&m,&k);
     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
     for(int i=1;i<=m;i++) scanf("%d",&b[i]);
     sort(b+1,b+1+m);
     ll l=-1e12,r=1e12;
     while(l<=r){
         ll mid=(l+r)/2;
         if(judge(mid)>=k)    l=(ans=mid)+1;
         else r=mid-1;
     }
    cout<<ans<<endl;
 }
posted @ 2020-01-12 23:46  overrate_wsj  阅读(229)  评论(0编辑  收藏  举报