Wannafly挑战赛29 A御坂美琴(思维题+dfs)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37025443/article/details/84568801

题意:

一开始有n个糖果,每一次操作,你可以选择一堆x将其分成两堆,x//2,x-x//2

直到一堆的糖果数量=1就不能进行操作了。

然后现在给你m堆糖果a[1..m],问你能不从n个通过任意操作变成当前的局面

解析:

官方题解:

我们维护当前堆的集合和⽬标集合,每次拿出当前个数最多的⼀堆,和⽬标中个数最多的⼀堆⽐较。如果当前的较 少,那么就是不能。如果相等,就把选出的这两堆扔掉,否则就对当前个数最多的那⼀堆进⾏⼀次操作。 如果操作次数⼤于 或者操作完之后当前堆的集合或⽬标集合还有剩余就是不能,否则就是能。

做的时候大佬发现只要a里面的数都可以通过n变换到,并且a[]的和=sum,那么就是可以的

#include <cstdio>
#include <cstring>
#include<algorithm>
#include<set>
using namespace std;
 
typedef long long ll;
const int MAXN = 1e5+100;
ll a[MAXN];
ll c[200];
int lnum[2];
ll lval[2];
int vis[2];
set<int> mm;
 
int main()
{
    ll n;
    int m;
    scanf("%lld%d",&n,&m);
    int maxx=0;
    int cnt=0;
    c[cnt++]=-n;
    ll yu=n;
    mm.insert(yu);
    while(n)
    {
        c[cnt++]=-n/2;
        n/=2;
        mm.insert(n);
        mm.insert(n+1);
    }
    mm.insert(2);
    mm.insert(1);
    //sort(c,c+cnt);
    ll sum=0;
    int flag=1;
    for(int i=1;i<=m;i++)
    {
        scanf("%lld",&a[i]);
        sum+=a[i];
        if(mm.count(a[i])==0)
        {
            flag=0;
        }
    }
    if(!flag||sum!=yu)
    {
        printf("ham\n");
    }
    else
    {
        printf("misaka\n");
    }
 
 
}

本来想在题解里面找证明的,但是发现这个直接暴力就可以做。

扫描二维码关注公众号,回复: 4894266 查看本文章

用dfs遍历这个操作得到的树,如果在遍历这棵树的时候,可以把a[]里面的数对应到每一个树的结点上,那么就是可以的

那么复杂度最多只会遍历树上的m条链,并且一旦你通过一条链遍历到叶子结点,那么肯定是不行的,这条链上没有点、

可以对应a[]中的数

dfs复杂度为O(m*logn)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>
#include <map>
#define pb push_back
#define mk make_pair
typedef long long ll;
using namespace std;
typedef pair<int,int> PII;
const int MAXN = 1e5+10;
const ll MOD = 998244353;
ll n,m;
map<ll,int> mp;

int f;

void dfs(ll x)
{
    if(!f) return ;
    if(mp[x])
    {
        mp[x]--;
        return ;
    }
    if(x==1) {f=0;return;}
    ll tmp=x/2;
    dfs(tmp);
    dfs(x-tmp);
}


int main()
{
    cin>>n>>m;
    ll v,sum=0;
    for(int i=1;i<=m;i++)
        cin>>v,mp[v]++,sum+=v;
    f=1;
    if(sum!=n) f=0;
    if(f) dfs(n);
    if(f){
        for(auto v:mp)
        {
            if(v.second>0)
                {f=0;break;}
        }
    }

    if(!f) cout<<"ham"<<endl;
    else cout<<"misaka"<<endl;

}

猜你喜欢

转载自blog.csdn.net/qq_37025443/article/details/84568801
今日推荐