A. Diversity
题意:给定字符串s,求至少换多少个字符,使得有k个不同的英文字母
思路: 有没有可能? 可能的话,是不是已经够了,还是不够?
#include<bits/stdc++.h>
#define bug cout <<"bug"<<endl
using namespace std;
typedef long long ll;
const int MAX_N=2000;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
map<char,int> mp;
int main(void){
char s[5000];
int k;
scanf("%s",s+1);cin >> k;
int len=strlen(s+1);
if(len<k){
cout <<"impossible"<<endl;
return 0;
}
else{
int cnt=0;
for(int i=1;i<=len;i++){
if(!mp[s[i]]) mp[s[i]]=1,cnt++;
}
if(cnt >= k) cout <<"0"<<endl;
else cout << k-cnt << endl;
}
}
B. Rectangles
题意:给一个二维矩阵(0,1),求一集合,如果只有集合只包含一个元素,一定满足要求 ; 如果>=2,所有元素(都是0或者都是1)要求在同一行或者同一列
思路:求组合数,小心1的情况算了2次.. mmp 居然把组合数求错了找不出bug ... 没注意过c[50][25]的大小超过int范围又wa了一次,是真的菜
#include<bits/stdc++.h>
#define bug cout <<"bug"<<endl
using namespace std;
typedef long long ll;
const int MAX_N=2000;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
int n,m;
ll ans1,ans0;
int a[60][60];
ll c[60][60];
void init(){
c[0][0]=c[1][0]=c[1][1]=1;
for(int i=2;i<=50;i++){
c[i][0]=1;
for(int j=1;j<=i;j++)
c[i][j]=c[i-1][j]+c[i-1][j-1];
}
}
void check1(){
for(int i=1;i<=n;i++){
int cnt0=0,cnt1=0;
for(int j=1;j<=m;j++){
if(a[i][j]==1) cnt1++;
else cnt0++;
}
if(cnt1>=2) for(int i=2;i<=cnt1;i++) ans1+=c[cnt1][i]/*,printf("c[%d][%d]=%d\n",cnt1,i,c[cnt1][i])*/;
if(cnt0>=2) for(int i=2;i<=cnt0;i++) ans0+=c[cnt0][i]/*,printf("c[%d][%d]=%d\n",cnt0,i,c[cnt0][i])*/;
}
return ;
}
void check2(){
for(int j=1;j<=m;j++){
int cnt0=0,cnt1=0;
for(int i=1;i<=n;i++){
if(a[i][j]==1) cnt1++;
else cnt0++;
}
if(cnt1>=2) for(int i=2;i<=cnt1;i++) ans1+=c[cnt1][i];
if(cnt0>=2) for(int i=2;i<=cnt0;i++) ans0+=c[cnt0][i];
}
return ;
}
int main(void){
init();
cin >> n >> m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
ll ans=n*m;
check1();
ans+=(ans1+ans0);
ans1=ans0=0;
check2();
ans+=(ans1+ans0);
cout << ans << endl;
return 0;
}
C. Sorting by Subsequences 思路:排序后给个序号,直接找环
#include<bits/stdc++.h>
#define FAST ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N=1e5+5;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
int a[MAX_N],b[MAX_N];
bool vis[MAX_N];
map<int,int> mp,mp1;
vector <vector<int> > ans;
void check(int i){
vector <int> t;
int now=a[i];
if(now==i){
vis[i]=true;
t.push_back(i);
ans.push_back(t);
return ;
}
while(1){
if(vis[now]) {break;}
t.push_back(now);
vis[now]=true;
// printf("%d ~\n",now);
now=a[now];
}
ans.push_back(t);
return ;
}
int main(void){
int n;cin >> n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
mp[b[i]]=i,mp1[i]=b[i];
for(int i=1;i<=n;i++) a[i]=mp[a[i]];
for(int i=1;i<=n;i++){
if(!vis[a[i]]) check(i);
}
// for(int i=1;i<=n;i++) printf("%d ",a[i]);
cout << ans.size() <<endl;
for(int i=0;i<(int)ans.size();++i){
vector <int> t=ans[i];
cout << t.size() <<" ";
for(int j=0;j<(int)t.size();++j) printf("%d ",t[j]); puts("");
}
return 0;
}
D. Interactive LowerBound 题意:交互题有一个升序排序,长度为n(1e5)的链表,每个节点有v,next . 最小值的编号为s,找到 所有>=x 中最小的值 , 且查询次数<=1999
思路:随机查询k次寻找 <=x中最靠近x的节点的next.保存mmax最大值.剩下1999-k次从next开始暴力搜索
找不到的概率为 (1-k/n)^(1999-k) 当k=1e3就非常的小. 我感觉很神奇 . 所谓的随机数算法
#include<bits/stdc++.h>
#define FAST ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N=1e5+5;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
int a[MAX_N],b[MAX_N];
bool vis[MAX_N];
map<int,int> mp,mp1;
vector <vector<int> > ans;
int main(void){
srand(time(NULL));
ll n,s,x;
int v,ac;
cin >> n>>s >> x;
int mmax=-1,index=s;//index=s写index=-1 wa 8
for(int i=1;i<=1000;++i){
int t=((1LL)*rand()*1998+rand())%n+1;
printf("? %d\n",t);
fflush(stdout);
scanf("%d%d",&v,&ac);
if(v<=x && v>mmax) mmax=v,index=ac;
}
if(mmax==x){
printf("! %d\n",mmax);
return 0;
}
else{
while(index!=-1){
printf("? %d\n",index);
fflush(stdout);
scanf("%d%d",&v,&ac);
mmax=max(mmax,v);
if(mmax>=x) break;
index=ac;
}
}
if(mmax>=x) printf("! %d\n",mmax);
else printf("! %d\n",-1);
fflush(stdout);
return 0;
}
E. Upgrading Tree
溜了