cf1530-CodeforcesRound733(div1+div2)A~D
题意:
定义:只包含0和1的十进制数称为(Binary Decimal),给定一个正整数N,求以最少的分解数量将其分解为Binary Decimal的分解数是多少。
思路:
分析样例,其实就是找各数位中最大的数,比如121->2,789->9
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define rep(i,a,n) for (int i=a;i<n;i++) 4 #define per(i,a,n) for (int i=n-1;i>=a;i--) 5 #define pb push_back 6 #define mp make_pair 7 #define all(x) (x).begin(),(x).end() 8 #define fi first 9 #define se second 10 #define SZ(x) ((int)(x).size()) 11 typedef vector<int> vint; 12 typedef long long ll; 13 typedef pair<int,int> PII; 14 typedef pair<ll,ll> PLL; 15 const int mod = 1e9+7; 16 ll qpow(ll a,ll b){ll res=1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res%mod;} 17 template<typename T> 18 inline void read( T&x ) 19 { 20 int f=1;x=0;char c=getchar(); 21 while(c>'9'||c<'0') 22 { 23 if(c=='-') f=-1;c=getchar();//ÅжÏÊÇ·ñΪ¸º 24 } 25 while(c>='0'&&c<='9') x=10*x+c-48,c=getchar(); 26 x=x*f; 27 } 28 int t; 29 string s; 30 int main(){ 31 read(t); 32 while(t--){ 33 cin>>s; 34 char minx='0'; 35 for(char c:s){ 36 minx=max(minx,c); 37 } 38 cout<<minx<<endl; 39 } 40 return 0; 41 }
题意:
给出n和m,求一个n*m的01矩阵,要求只有四条边有1,中间全是0,且每个1附近八个方向的八个点都是0
思路:
贪心
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define rep(i,a,n) for (int i=a;i<n;i++) 4 #define per(i,a,n) for (int i=n-1;i>=a;i--) 5 #define pb push_back 6 #define mp make_pair 7 #define all(x) (x).begin(),(x).end() 8 #define fi first 9 #define se second 10 #define SZ(x) ((int)(x).size()) 11 typedef vector<int> vint; 12 typedef long long ll; 13 typedef pair<int,int> PII; 14 typedef pair<ll,ll> PLL; 15 const int mod = 1e9+7; 16 ll qpow(ll a,ll b){ll res=1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res%mod;} 17 template<typename T> 18 inline void read( T&x ) 19 { 20 int f=1;x=0;char c=getchar(); 21 while(c>'9'||c<'0') 22 { 23 if(c=='-') f=-1;c=getchar();//ÅжÏÊÇ·ñΪ¸º 24 } 25 while(c>='0'&&c<='9') x=10*x+c-48,c=getchar(); 26 x=x*f; 27 } 28 int t,n,m; 29 int matrix[50][50]; 30 int main(){ 31 read(t); 32 while(t--){ 33 memset(matrix,0,sizeof(matrix)); 34 read(n);read(m); 35 int i; 36 for(i=1;i<=m;i+=2) matrix[1][i]=1; 37 for(i=3;i<=n;i+=2) matrix[i][1]=matrix[i][m]=1; 38 39 for(int j=3;j<=m-2;j+=2) matrix[n][j]=1; 40 for(i=1;i<=n;++i) { 41 for(int j=1;j<=m;++j) cout<<matrix[i][j]; 42 cout<<endl; 43 } 44 } 45 return 0; 46 }
题意:
给出A,B两个长度为N的数组,定义数组的有效得分为最大的前(L-L/4)个分数之和,其中L为数组长度。求这两个数组需要增加同时多少个元素,才能是的A的得分大于B
补充条件:数组中的每个元素Ai∈[0, 100]
思路:
观察样例,最优解是A每次增加值为100的元素,B每次增加值为0的元素。
先将B的结果预处理出来,因为B每次都增加0,所以被算入总分的部分不会有变动,只会有慢慢扩张到最后停滞。详见代码第41~42行
预处理A在数组长度为 k 时候的结果,需要将增加了x个元素直接算入总和当中,在添加A数组当中的(k-k/4-x)的前缀和。详见代码第40行与第24~27行。
根据算出来的A和B,二分需要增加的场数x。
代码:
#include <bits/stdc++.h> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef vector<int> vint; typedef long long ll; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; const int mod = 1e9+7; ll qpow(ll a,ll b){ll res=1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res%mod;} const int N=4e5+5; int t,n,a[N],b[N]; ll sa[N],sb[N]; inline bool cmp(int a,int b){ return a>b; } inline bool check(int x){ int ssa=x*100; int y=x+n; int tmp=y-y/4; ssa+=sa[tmp-x]; return ssa<sb[tmp]; } int main(){ ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>t; while(t--){ cin>>n; sa[0]=sa[1]=sb[0]=sb[1]=0; rep(i,1,n+1) cin>>a[i]; rep(i,1,n+1) cin>>b[i]; sort(a+1,a+n+1,cmp); sort(b+1,b+n+1,cmp); rep(i,1,n+1) sa[i]=sa[i-1]+a[i]; rep(i,1,n+1) sb[i]=sb[i-1]+b[i]; rep(i,n+1,2*n+1) sb[i]=sb[i-1]; //cout<<"\nsahesb\n"; //rep(i,1,2*n+1) cout<<sa[i]<<' ';cout<<endl; //rep(i,1,2*n+1) cout<<sb[i]<<' ';cout<<endl; //cout<<"begin"<<sa[n-n/4]<<' '<<sb[n-n/4]<<' '<<n-n/4<<endl; if(sa[n-n/4]>=sb[n-n/4]) { cout<<0<<endl; continue; } int l=0,r=n; while(l<r){ int mid=(r+l)>>1; if(check(mid)) l=mid+1; else r=mid; } cout<<l<<endl; } return 0; }
题意:
给出一个数组 A,求一个排列 B,使得,对于所有的 Bi 不等于 i ,且 Ai 与 Bi 相等的次数最多。
思路:
相等次数最多先直接贪心,把未被访问过的 Ai 都保存到 Bi 当中。需要统计相等的次数,该匹配次数即为最终结果次数。
求排列 B 就比较费心思,
如果全部匹配了,就输出数组 B ,
如果匹配数 cnt == n-1,即还有一个未被匹配,
如果剩余的空位和剩余的数字相等,就把该空位填上原本对应的 A 中的数字,然后将 B 中原本填着该 A 的位置填上剩余的数字。
如果不相等则直接把空位不上去。
如果匹配数 cnt < n-1,则必有一种方法可以使得剩余的数通过排列得到结果,详见代码46~73行。
代码:
#include <bits/stdc++.h> using namespace std; #define rep(i,a,n) for (register int i=a;i<n;i++) const int N=2e5+5; int t,n,a,b[N],aa[N],aaa[N]; bool vis[N]; int main(){ ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>t; while(t--){ cin>>n; memset(vis,0,sizeof(bool)*(n+1)); memset(b,0,sizeof(int)*(n+1)); int cntpp=0; rep(i,1,n+1){ cin>>a;aa[i]=a; if(!vis[a]){ vis[a]=1; b[i]=a; aaa[a]=i; cntpp++; } } if(cntpp==n){ cout<<n<<'\n'; rep(i,1,n+1) cout<<b[i]<<" "; cout<<'\n'; continue; } if(cntpp==n-1){ int ss,sb; rep(i,1,n+1) { if(!vis[i]) ss=i; if(!b[i]) sb=i; } if(ss==sb) { b[sb]=aa[sb]; b[aaa[aa[sb]]]=ss; } else b[sb]=ss; cout<<cntpp<<'\n'; rep(i,1,n+1) cout<<b[i]<<" "; cout<<'\n'; continue; } int now=1; int kj; for(register int i=1;i<=n;++i){ if(b[i]==0){ while(vis[now]&&now<=n+1) ++now; if(i!=now){ vis[now]=1; b[i]=now; kj=i; //cout<<now<<"az\n"; } else{ int tmp=now+1; while(vis[tmp]&&tmp<=n+1) ++tmp; if(tmp<=n){ vis[tmp]=1; b[i]=tmp; kj=i; } else{ b[i]=b[kj]; b[kj]=now; vis[now]=1; } //cout<<tmp<<"666\n"; } } } cout<<cntpp<<'\n'; rep(i,1,n+1) cout<<b[i]<<" "; cout<<'\n'; } return 0; }