每日一题: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 :

 

 

 

posted on 2020-04-30 06:16  黑暗尽头的超音速炬火  阅读(235)  评论(0编辑  收藏  举报