zoukankan      html  css  js  c++  java
  • URAL2049 Chemistry

    Link
    先判断(k=n),很显然有解的充要条件是(n=2^t(tinmathbb N)),构造用二进制合并就行了。
    然后若(2 mid n),那么此时一定有解,依旧可以类似地二进制分组构造。
    (2|n),那么有解的充要条件是(k e n-1),构造方法依旧是二进制分组。

    #include<cstdio>
    #include<vector>
    #include<utility>
    #define fi first
    #define se second
    using pi=std::pair<int,int>;
    std::vector<pi>ans,tmp;
    void out(){printf("%d
    ",(int)ans.size());for(pi x:ans)printf("%d %d
    ",x.fi,x.se);}
    void merge(pi&a,pi&b){ans.push_back({a.fi,b.fi}),a.se-=b.se,b.se*=2;}
    int main()
    {
        int n,k,f=0;scanf("%d%d",&n,&k);
        if(k==1) return puts("0"),0;
        if(n==k&&__builtin_popcount(n)^1) return puts("-1"),0;
        if(k==n-1&&~n&1) return puts("-1"),0;
        if(n==k)
        {
    	for(int i=1;i<n;i+=i) for(int j=1;j<=n;j+=i+i) ans.push_back({j+i,j});
    	return out(),0;
        }
        if(k&1) f=1,++k;
        for(int i=17,p=1;~i;--i)
        {
    	if(!((k+1)>>i&1)) continue;
    	tmp.push_back({p,1<<i});
    	for(int j=1;j<1<<i;j+=j) for(int k=0;k<1<<i;k+=j+j) ans.push_back({p+j+k,p+k});
    	p+=1<<i;
        }
        while(tmp.size()>2) for(merge(tmp.front(),tmp.back());tmp.back().se==prev(prev(tmp.end()))->se;tmp.pop_back()) merge(tmp.back(),*prev(prev(tmp.end())));
        for(int p;tmp.front().se^k;) p=tmp[0].se<tmp[1].se,merge(tmp[p],tmp[!p]);
        if(f) ans.push_back({1,tmp[1].fi});
        out();
    }
    
  • 相关阅读:
    composer 安装laravel
    面向对象
    dedecms常用标签
    Illegal modifier for parameter *** , only final is permitted”
    import static和import的区别
    <<Effective Java>> 第四十三条
    java valueOf
    linux的shell编程
    DFA和NFA的区别
    发现一个正则网
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12614868.html
Copyright © 2011-2022 走看看