繁体   English   中英

Elevenagram Round H Google Kickstart

[英]Elevenagram Round H google kickstart

我一直在试图了解从Kickstart中圆形H 2019的解决问题的办法elevanagram https://codingcompetitions.withgoogle.com/kickstart/round/0000000000050edd/00000000001a286d

给定一个由1到9的数字组成的数字,您可以重新排列这些数字以创建一个可被11整除的数字吗?

由于数量可能很大,因此您会得到整数A1,A2,...,A9。 号码i中有i个数字,代表所有i。

输入输入的第一行给出测试用例的数量,T。T行>跟随。 每行包含九个整数A1,A2,...,A9。

输出:对于每个测试用例,输出包含Case #x:y的一行,其中x是>测试用例编号(从1开始),如果数字可以重新排列以创建11的倍数,则y是YES。除此以外。

限制时间限制:每个测试集20秒。 内存限制:1GB。

对于所有i,测试集1(可见):0≤Ai≤20。

测试集2(隐藏):对于所有i,0≤Ai≤10 ^ 9。

问题分析表明:假设i的正数为Pi,i的负数为Ai-Pi。 然后,我们将具有以下三个方程式:

(1)∑ Pi =面值(sum(A)/ 2)

(2)Σi×(Pi-(Ai-Pi))%11 = 0

(3)0≤Pi≤Ai

为了解决这个问题,首先我们可以将每个数字的一​​半放在正数分区中(例如,Pi = Ai / 2,注意奇数),然后尝试调整每个Pi来满足等式(2)。 对于每个i,我们可以将其Pi从-Ai / 2调整为Ai / 2。

我们可以证明以下两个结论:

如果Ai≥10的数目至少为两个,则解必须存在。

这很容易证明。 我们只能将这两个数字从-5调整到5,每次调整将导致模数11的剩余值不同。因此,最终我们将得到0。

如果至少有三个Ai≥6,那么该解必须存在。

为了证明这一点,我们可以证明:

对于任何1≤i <j <k≤9,0≤r≤10,以下等式:

(1)(i * x1 + j * x2 + k * x3)%11 = r

(2)x1 + x2 + x3 = 0

(3)-3≤xi≤3

将有一个有效的解决方案。

为什么至少有2个数字的count> = 10或什至一个数字的count> = 20是正确的,所以解决方案总是存在的?对这两个都有简单的数学证明吗? 另外,我正在提交相同的问题。

   #include <iostream>
   #include <algorithm>
   #include <fstream>
   #include <vector>
   #include <deque>
   #include <assert.h>
   #include <queue>
   #include <stack>
   #include <set>
   #include <map>
   #include <stdio.h>
   #include <string.h>
   #include <utility>
   #include <math.h>
   #include <bitset>
   #include <iomanip>
   #include <complex>

   using namespace std;

   #define rep(i, a, b) for (int i = (a), i##_end_ = (b); i < i##_end_; ++i)
   #define debug(...) fprintf(stderr, __VA_ARGS__)
   #define mp make_pair
   #define x first
   #define y second
   #define pb push_back
   #define SZ(x) (int((x).size()))
   #define ALL(x) (x).begin(), (x).end()

   template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
   template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
   template<typename T> inline bool smin(T &a, const T &b)   { return a > b ? a = b : a;    }
   template<typename T> inline bool smax(T &a, const T &b)   { return a < b ? a = b : a;    }

   typedef long long LL;

   const int N = (int) 505, mod = (int) 0;
   int cnt[10], dp[N][11], odp[N][11];
   int main() {
        int tc;
        cin >> tc;
        for (int tt = 1; tt <= tc; ++tt) {
            cout << "Case #" << tt << ": ";
            int sum = 0;
            for (int j = 1; j < 10; ++j) {
                cin >> cnt[j];
                if (cnt[j] > 20) {
                    cnt[j] = 20 + (cnt[j] & 1); 
                }
                sum += cnt[j];
            }
            memset(dp, 0, sizeof dp);
            dp[0][0] = 1;
            for (int j = 1; j < 10; ++j) {
                memcpy(odp, dp, sizeof dp);
                memset(dp, 0, sizeof dp);
                for (int pick = 0; pick <= cnt[j]; ++pick) {
                    for (int lpick = 0; lpick + pick < N; ++lpick) {
                        for (int lmod = 0; lmod < 11; ++lmod) {
                            int nmod = (lmod + pick * j + (11 - j) * (cnt[j] - pick)) % 11;
                            dp[lpick + pick][nmod] |= odp[lpick][lmod];
                        }
                    }
                }
            }
            if (dp[sum / 2][0]) {
                cout << "YES\n";
            } else {
                cout << "NO\n";
            }

        }
   }



我知道为什么所有计数都减少到最多20个,但是为什么我们还要循环处理残渣类呢? 为什么我们将残渣添加到实际获得的残渣中? 请帮助。我已经尝试了两天,但没有成功的逻辑。任何帮助如何去理解问题表示赞赏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM