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