每日一题:a question a day keeps the offer near
我是蜗牛,所以没资格偷懒
大数怎么组合
感谢大佬
https://zhuanlan.zhihu.com/p/115820262
https://github.com/Akeepers/algorithm/blob/master/kick%20start/2020/A/C.cpp
https://codingcompetitions.withgoogle.com/kickstart/round/000000000019ffc7/00000000001d3f5b
1.plates
做题一定要改变量,并且先自己做,不然绝对理解不了题意。一定要换变量描述,不然就是照抄,没一点区别。昨晚把我熬死了快。感觉没毛病,一直报错
这是一个动态规划的题
分三个存储vector
第一个存所有输入值,第二个存sum,第三个存dp值
特别之处:存sum的第一位空0,没当找第k个这种问题,就要考虑,我实际下标是找k还是k-1呢。若欲找k,需挪下标,否则算k,需减下标,脑子要清楚!!!
这个就难为在这句话了min(j,n)才对,写成k这个min毫无意义,还会出现下面的情况。因为这个sum含义是在第i-1个取p个,所以必须是比列数小,因为要真实存在!!
for(int p=0;p<=min(j,k);++p)
store[i][j]=max(store[i][j],store[i-1][j-p]+sum[i-1][p]);
改好之后!!
input:
2
4 1 3
10
10
100
30
3 2 3
80 80
15 50
20 10
注意输入测试的多样性,横着来,竖着也来
#include<bits/stdc++.h>
#define TEST
using namespace std;
//dp[i][j] first i plates sum is j
//12 23 250
//70 9 1 find large 4
int main()
{
#ifdef TEST
freopen("a.out","r",stdin);
#endif
int T;
cin>>T;
for(int o=1;o<=T;++o)
{
int m,n,k,ans=0;
cin>>m>>n>>k;
// cout<<m<<n<<k<<endl;
vector<vector<int>> stone(m,vector<int>(n,0));
vector<vector<int>> sum(m,vector<int>(n+1,0));;
vector<vector<int>> store(m+1,vector<int>(k+1,0));
for(int i=0;i<m;++i)
{
for(int j=0;j<n;++j)
{
cin>>stone[i][j];
}
}
for(int i=0;i<m;++i)
{
for(int j=1;j<=n;++j)
{
sum[i][j]=(sum[i][j-1]+stone[i][j-1]);
}
}
for(int i=0;i<m;++i)
{
for(int j=0;j<=n;++j)
{
cout<<sum[i][j]<<" ";
}
cout<<endl;
}
// sum=stone;
//build stone store
//build dp array
int l=min(k,n);
// for(int c=1;c<=l;++c)
// {
// for(int g=0;g<m;++g)
// store[g][c]=stone[g][c-1];
// }
//// store[0]=stone[0];
// for(int j=1;j<=l;++j)
// {
// for(int g=0;g<m;++g)
// store[g][j]+=store[g][j-1];
// }
for(int i=1;i<=m;++i)
{
for(int j=1;j<=k;++j)
{
for(int p=0;p<=min(j,n);++p)
store[i][j]=max(store[i][j],store[i-1][j-p]+sum[i-1][p]);
}
}
for(int i=0;i<=m;++i)
{
for(int j=0;j<=k;++j)
{
cout<<store[i][j]<<" ";
}
cout<<endl;
}
cout<<"Case #"<<o<<": "<<store[m][k]<<endl;
}
return 0;
}
2.workout
这种题竟然用二分法解,太会玩了
注意点3个:
define后先写代称再写全称
llabs用变量代替,当其可整除时,只用一个分隔符就够。所以减一
最后返回的是left??这里还没想通
#include<bits/stdc++.h>
#define ll long long
// #define TEST
using namespace std;
//dp[i][j] first i plates sum is j
//12 23 250
//70 9 1 find large 4
bool truely(ll n,ll mid,vector<int>& stone)
{
int cnt=0;
for(int i=1;i<stone.size();++i)
{
if(llabs(stone[i]-stone[i-1])>mid)
{
cnt+=(llabs(stone[i]-stone[i-1]))/mid;
if(llabs(stone[i]-stone[i-1])%mid==0) cnt--;
}
if(cnt>n) return false;
}
//if(cnt<=n) return true;
return true;
}
int main()
{
// #ifdef TEST
// freopen("a.out","r",stdin);
// #endif
int T;
cin>>T;
for(int o=1;o<=T;++o)
{
int m,n;
cin>>m>>n;
vector<int> stone(m,0);
ll max_heap=INT_MIN;
for(int i=0;i<m;++i)
{
cin>>stone[i];
if(i==0) continue;
else
{
if(llabs(stone[i]-stone[i-1])>max_heap)
{
max_heap=llabs(stone[i]-stone[i-1]);
}
}
}
ll l=1,r=max_heap,mid=0;
while(l<=r)
{
mid=(l+r)/2;
// if(l<1)
// {
// l=1;break;
// }
if(truely(n,mid,stone))
{
r=mid-1;
}
else
{
l=mid+1;
}
}
cout<<"Case #"<<o<<": "<<l<<endl;
}
return 0;
}
4.workout
给一堆数组。string类型,把其转为k个一组的问最大得分。每组得分是最大前缀。所以用字典树
分为typedef定义,插入,查询
计算个数的原理==每个节点插入进去,就把计数变量++;从根节点开始递归寻找
终止条件是:若当前节点不存在。返回0
否则把每个的计数值/k.k个一组。总共能分多少组前缀是当前值。是的话,就共有一个元素,结果为1.总共结果加起来。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define endl "\n"
const int N=1e5+5;
typedef struct node
{
node* idx[26];
int tot=0;
}trie;
node* head;
void inserts(string& s)
{
node* cur=head;
for(int i=0;i<s.size();++i)
{
int tmp=s[i]-'A';
if(!cur->idx[tmp]) cur->idx[tmp]=new trie();
cur=cur->idx[tmp];
cur->tot++;
}
}
int n,k;
string arr[N];
int query(node* cur)
{
if(!cur) return 0;
int ans=cur->tot/k;
for(int i=0;i<26;++i)
{
if(cur->idx[i]) ans+=query(cur->idx[i]);
}
return ans;
}
int32_t main()
{
IOS;
int T;
cin>>T;
for(int o=0;o<T;o++)
{
cin>>n>>k;
head=new trie();
for(int i=0;i<n;++i)
{
cin>>arr[i];
inserts(arr[i]);
}
int ans=query(head);
cout<<"Case #"<<o+1<<": "<<ans<<endl;
}
return 0;
}
RoundB:
1.这题和A的workout很像,具体表现是:在某个范围内要找某个值,是最大能满足某种特征的元素。都可以用二分做:二分最重要的是判断 l<r ||l<=r循环关系维系的依据。判断某个条件函数后,对l/r的取值操作。中心思想是不能造成死循环,一般都是试验成功了,l=mid,否则r=mid-1
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl "\n"
#define ll long long
ll arr[1006];ll N,D;
bool ok(ll mid)
{
for(int i=0;i<N;++i)
{
if(mid%arr[i]) mid+=(arr[i]-mid%arr[i]);
}
if(mid>D) return false;
return true;
}
int main()
{
int T;
cin>>T;
for(int o=1;o<=T;++o)
{
cin>>N>>D;
for(int i=0;i<N;++i)
{
cin>>arr[i];
}
ll l=0,r=D;
while(l<r)
{
ll mid=(l+r+1)/2;
if(ok(mid)) l=mid;
else r=mid-1;
}
cout<<"Case #"<<o<<": "<<l<<endl;
}
return 0;
}
3.机器人路径规划问题
总共10^9的行/列
(w,h)w列 h行 注意这个反人类的设定 先列后行
起始点(1,1)
NSWE 代表向不同方向
指令存在嵌套 最难的就是这种有嵌套的
3(S2(E))
is equivalent to SEESEESEE
整个棋盘环状,走出去还会回来 10^9->1
问:给出指令 求坐标
直接按照指令拆解会MLE,so看看简单做法
最大的难缠点在于:给了那么多弯弯绕指令,其实不用,只考虑终点的话,先左再右,和先右再左,没有一毛钱的区别!!以前觉得和字符串拆分像,就是把指令拆开一条条执行,实际会非常慢,指令拆开占用了十分多的功夫,所以这道题,竟然是用相似的题眼迷惑大家,不小心走向字符串拆分,就是一条不归路了。
这次代码还学到了 assert(0);用法(zbsqmsbb)if后最好和else if配合使用这样显得比较完备,最后所有情况都说过了,还剩else可后接assert(0); assert是断言,内部如果为假就报错RE,assert(0)是永远报错,用于一些绝对不可能出现的场合
#include<bits/stdc++.h> using namespace std; #define ll long long int main() { ll mod=1e9; int T,cc=1; cin>>T; while(T--) { deque<ll> p; cout<<"Case #"<<cc++<<": "; string s; ll x=0,y=0; cin>>s; p={1}; for(auto c:s) { if(c>='2'&&c<='9') p.push_back(p.back()*(c-'0')%mod); else if(c=='N') y=((y-p.back())%mod+mod)%mod; else if(c=='S') y=(y+p.back())%mod; else if(c=='W') x=((x-p.back())%mod+mod)%mod; else if(c=='E') x=(x+p.back())%mod; else if(c=='(') continue; else if(c==')') p.pop_back(); else assert(0); } cout<<x+1<<" "<<y+1<<endl; } return 0; }
H -index
main idea:(not clear,example shows more:)
find H-index in an array
H-index: the max val of first index of array;
such as:
1 2 1——》1 1 1
first: only one
two:only two one
Input |
Output |
2 3 5 1 2 6 1 3 3 2 2 15 |
Case #1: 1 1 2 Case #2: 1 1 2 2 2 3 |
This is a special answer,for the reason it use many new function in C11,change stable of code.So we need to learn first:
1.emplace_back(){better}==push_back()
emplace_back() better avoid the memory copy and move,so that container insert element performance is further improved.Priority should be given in most cases;
2.make_heap
usage:change vector into heap==priority_queue
3params: container begin end greater/less
the function generates a big heap by default
PS:the literal meaning is opposite
greater<==>min heap
less<==>max heap
vector<int> minHeap; //don't forget parentheses in the end make_heap(minHeap.begin(),minHeap.end(),greater<int>());
3.push_heap /pop_heap
cannot understand what the function is saying
example show usage:
m-countdown
most special point is :