9/12 思维训练

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了9/12 思维训练相关的知识,希望对你有一定的参考价值。

C. Digital Logarithm
使用优先队列模拟这个元素消去的过程。

#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=7e5+5;
const int inf=1e18;
const int mod=1e9+7;
int fac[40];
int qpow(int a,int b)
    int res=1;
    while(b)
    
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    
    return res;

int getinv(int x)return qpow(x,mod-2);
int C(int a,int b)

    return (fac[a]*getinv(fac[a-b])%mod)*getinv(fac[b])%mod;


int n;
priority_queue<int>a,b;
void solve()

    cin>>n;
    for(int i=1;i<=n;i++)
        int x;cin>>x;
        a.push(x);
    
    for(int i=1;i<=n;i++)
        int x;cin>>x;
        b.push(x);
    
    int ans=0;
    while(!a.empty()&&!b.empty())
    
        int x=a.top();
        int y=b.top();
        if(x==y)
        
            a.pop();b.pop();continue;
        
        ans++;
        if(x>y)
        
            a.pop();
            a.push(to_string(x).length());
        
        else
        
            b.pop();
            b.push(to_string(y).length());
        
    
    cout<<ans<<endl;

signed main()

    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;


G. Good Key, Bad Key
假设两个箱子x和y:
先好钥匙开x再坏钥匙开y:x-k+y/2
先坏要是开x再好钥匙开y: x/2+y/2-k
因此可发现坏要是后面不能接好钥匙,只能接坏钥匙。
暴力求解从何处开始只开坏箱子。

#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=7e5+5;
const int inf=1e18;
const int mod=1e9+7;
int fac[40];
int qpow(int a,int b)
    int res=1;
    while(b)
    
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    
    return res;

int getinv(int x)return qpow(x,mod-2);
int C(int a,int b)

    return (fac[a]*getinv(fac[a-b])%mod)*getinv(fac[b])%mod;

int n,k,a[N];
void solve()

    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    int ans=0,sum=0;
    for(int i=1;i<=n;i++)
    
        int tp=sum;
        for(int j=i;j<=min(i+32,n);j++)
        
            int g=a[j];
            g>>=j-i+1;
            tp+=g;
        
        ans=max(ans,tp);
        sum+=a[i]-k;
    
    ans=max(ans,sum);
    cout<<ans<<endl;

signed main()

    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;


C. Infected Tree
简单树形dp,没写出来不应该。
状态转移方程:f[x]=max(f[x],f[y]+sz[x]-sz[y]-2);
删除一个分支节点,需要减去2(结点本身和子结点),加上被感染结点最多可保留的符合条件的节点数

#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=7e5+5;
const int inf=1e18;
const int mod=1e9+7;
int fac[40];
int qpow(int a,int b)
    int res=1;
    while(b)
    
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    
    return res;

int getinv(int x)return qpow(x,mod-2);
int C(int a,int b)

    return (fac[a]*getinv(fac[a-b])%mod)*getinv(fac[b])%mod;

int n,ans,sz[N],f[N];
bool vis[N];
vector<int>e[N];
bool cmp(int a,int b)return a>b;
void dfs(int x,int pre)

    sz[x]=1;
    for(int y:e[x])
    
        if(y==pre) continue;
        dfs(y,x);
        sz[x]+=sz[y];
    
    for(int y:e[x])
    
        if(y==pre) continue;
        f[x]=max(f[x],f[y]+sz[x]-sz[y]-2);
    
    for(int y:e[x])
    
        if((pre==0&&e[x].size()==1)||(pre!=0&&e[x].size()==2))
           f[x]=max(f[x],sz[x]-2);
    

void solve()

    cin>>n;
    for(int i=0;i<=n;i++)
        sz[i]=f[i]=0,e[i].clear();
    for(int i=1;i<n;i++)
    
        int u,v;cin>>u>>v;
        e[u].push_back(v);e[v].push_back(u);
    
    dfs(1,0);
    cout<<f[1]<<endl;


signed main()

    ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;


C. Binary String
题意:在一个01字符串中,可从左右两端删除任意的字符,删除1的数目和字符串中0的数目去最大值,要求让这个最大值最小
思路:
s1表示任意字符串的长度,t1字符串中1的数目,t0表示任意字符串中1的数目
不细说了,最后可化简为s1-t1=t0,及求出字符’0‘的前缀和,保证这个差值最大即可,区间长度为1的数目。

#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=7e5+5;
const int inf=1e18;
const int mod=1e9+7;
int fac[40];
int qpow(int a,int b)
    int res=1;
    while(b)
    
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    
    return res;

int getinv(int x)return qpow(x,mod-2);
int C(int a,int b)

    return (fac[a]*getinv(fac[a-b])%mod)*getinv(fac[b])%mod;

bool cmp(int a,int b)return a>b;
int n,ans,sum[N];
bool vis[N];
vector<int>e[N];

void solve()

    string s;cin>>s;
    int g=count(s.begin(),s.end(),'1'),n=s.length();
    s=" "+s;
    for(int i=1;i<=n;i++)
    
        sum[i]=sum[i-1]+(s[i]=='0');
    
    int ans=g;
    for(int i=g;i<=n;i++)
        ans=min(ans,sum[i]-sum[i-g]);
    cout<<ans<<endl;

signed main()

    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;


A. The Enchanted Forest
感谢队友对于本题数学公式的解释,妙啊
思路:
容易看出分为k<=n和k>n两种情况,每种情况都要考虑增加蘑菇;前者为k*(k-1)/2,后者由于肯定会经过这n个点,因此不妨走到一端后,变保持自己的位置不动,(保持不动我是真的没想到),但是蘑菇数还是再增加的,当实践还剩k-n秒时,我们就要去收割那些本来就有的蘑菇和长处的蘑菇了,此时租箱另一端,在这个过程中,本来保持不懂的端点长出了n个蘑菇踩不到,相邻的一个点有n-1个蘑菇踩不到……以此类推,总数为n*(n+1)/2个蘑菇踩不到。

#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=7e5+5;
const int inf=1e18;
const int mod=1e9+7;
int fac[40];
int qpow(int a,int b)
    int res=1;
    while(b)
    
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    
    return res;

(转)蘑菇街如何通过构建平台搞定数据标注难题?

《麦肯锡方法》第12章 管理公司的内部沟通-思维导图

《麦肯锡方法》第12章 管理公司的内部沟通-思维导图

儿童节,和 AI 一起通关 “超级马里奥兄弟”

思维专题(不定期更新)

百科知识 画法几何创造性思维训练