CF1552D(思维,构造)

CF1552D(思维,构造)

题意

给一个序列 a。问能不能构造一个 b 使得 bi+bj=ak 对所有的 1kn 成立。

思路

一开始瞎写了一个这样的构造方案:b=(x,x+a2,x+a3,...,x+an) 。显然现在如果能把 a1 搞出来就行了。然后减一减,就有 bibj=ai+1aj+1=a1 。之后枚举一下感觉就行了,然后发现样例都寄了··

上面的构造法肯定是没问题的,也就是这只是一个必要条件。之后又想了一个新构造:b=(x,x+a2,x+a2+a3,...,x+a2+a3...+an) 。和上面的构造起到了一样的效果。

之后,猜了一个结论:如果 s1+x(x+s2)=s1s2=ai 成立就一定有解,其中 s1,s2a 中随便的一些数的和。把上面式子变形,ai 也可以扔到和式里,因此找序列中是否有两个值相同的和。这个二进制枚举搞搞。

之后也确实AC了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<stack>
#include<string>
#include<random>
#include<iomanip>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;

void solve()
{    
    int n; cin >> n;
    vector<int> a(n);
    rep(i,1,n) cin >> a[i - 1];
    set<ll> s;
    for(int i = 0;i < 1ll << n;i ++) {
        ll sum = 0;
        for(int j = 0;j < n;j ++) 
            if(i >> j & 1) sum += a[j];
        s.insert(sum);
    }
    cout << ((int)s.size() != (1 << n) ? "YES\n" : "NO\n");
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int T;cin>>T;
    while(T--)
        solve();

    return 0;
}

之后看了看题解,由于已经确定了 n1 个数字,因此如果一个数能被其他数字表示出来,那就一定有解 这句话就很好解释结论的正确性。


官方题解给了一种建边的思考方向,将 bibj 看成一条边 (i,j) 。要表示 n 个数字,则这个构造出的图一定有环。考虑这个环,按连边定义来看,这个环转一圈的权值和为 0 。这就是有解的必要条件。至于充分性,不在环上的边不讨论,环上边如果能通过构造一组解使得其和为0,设环边数 k ,此时还有 nk 条边,让其他点和环上任意点连接即可构造成功。

posted @   Mxrurush  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示