Nebius Welcome Round (Div. 1 + Div. 2) (C~D)

文章介绍了两道编程竞赛题目,C.PullYourLuck关键在于理解模运算的周期性和逆元概念,证明了当n为奇数时最小周期为n,n为偶数时为2n。D.Accommodation是关于公寓房间的亮度分配问题,提出了通过贪心策略求解最大和最小明亮公寓数量的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C. Pull Your Luck

https://codeforces.com/contest/1804/problem/C

题意:是否存在一个 a ≤ p a\leq p ap使得 ( x + a ∗ ( a + 1 ) 2 ) % n = 0 (x+\frac{a*(a+1)}{2} )\%n=0 (x+2a(a+1))%n=0

n ( 1 ≤ ∑ n ≤ 2 ⋅ 1 0 5 ) , p ( 1 ≤ p ≤ 1 0 9 ) n(1\leq \sum n\leq 2\cdot10^5),p(1\leq p\leq 10^9) n(1n2105),p(1p109)

思路:枚举a。容易发现对 a ∗ ( a + 1 ) 2 % n \frac{a*(a+1)}{2} \%n 2a(a+1)%n是有周期性的。
结论: 当n为奇数时最小周期为n,n为偶数时为2n

证明:

a ∗ ( a + 1 ) 2 % n ⇔ ( a % n ) ∗ ( ( a + 1 ) % n ) ∗ i n v ( 2 ) \frac{a*(a+1)}{2}\%n \Leftrightarrow (a\%n)*((a+1)\%n)*inv(2)%n 2a(a+1)%n(a%n)((a+1)%n)inv(2)

i n v ( 2 ) inv(2) inv(2)为2在模n下的逆元,当逆元存在的时候,很明显周期T=n。

  • 当n为奇数 i n v ( 2 ) = n + 1 2 inv(2)=\frac{n+1}{2} inv(2)=2n+1,因为 ( 2 ∗ n + 1 2 ) % n = 1 (2*\frac{n+1}{2})\%n=1 (22n+1)%n=1

  • 当n为偶数时,逆元不存在:定义a存在逆元,存在一个x使得 a x ≡ 1 ax\equiv 1 ax1,也即 a x + n y = 1 ax+ny=1 ax+ny=1存在正整数解x。
    而由扩展欧几里得可知, a x + n y = 1 ax+ny=1 ax+ny=1有解的必要条件是 1 = g c d ( a , n ) 1=gcd(a,n) 1=gcd(a,n),而 g c d ( a , n ) ≥ 2 ≠ 1 gcd(a,n)\ge2 \ne1 gcd(a,n)2=1故逆元不存在。
    在逆元不存在的情况下,上式就不成立了。
    我们令周期为kn(容易知道周期肯定是n的倍数),有
    a ∗ ( a + 1 ) 2 % n = ( a + k n ) ∗ ( a + k n + 1 ) 2 % n \frac{a*(a+1)}{2}\%n=\frac{(a+kn)*(a+kn+1)}{2}\%n 2a(a+1)%n=2(a+kn)(a+kn+1)%n
    = a 2 + a + 2 k n a + k n + k 2 n 2 2 =\frac{a^2+a+2kna+kn+k^2n^2}{2} =2a2+a+2kna+kn+k2n2
    = a 2 + a 2 % n + k n + k 2 n 2 2 % n =\frac{a^2+a}{2}\%n+\frac{kn+k^2n^2}{2}\%n =2a2+a%n+2kn+k2n2%n
    = a ∗ ( a + 1 ) 2 % n + k n + k 2 n 2 2 % n =\frac{a*(a+1)}{2}\%n+\frac{kn+k^2n^2}{2}\%n =2a(a+1)%n+2kn+k2n2%n
    那么,我们就需要后面一项 k n + k 2 n 2 2 % n = 0 \frac{kn+k^2n^2}{2}\%n=0 2kn+k2n2%n=0,很明显k=2时该式子为0。

AC代码

int calc(int x) {
    return x * (x + 1) / 2;
}
void solve() {
    cin >> n >> x >> p;
    for (int i = 1; i <= min((n & 1) ? n : n << 1, p); i++) {
        if ((calc(i) + x) % n == 0) {
            cout << yes;
            return;
        }
    }
    cout << no;
}

D. Accommodation (贪心)

https://codeforces.com/contest/1804/problem/D

题意:有n层公寓,每层m个窗户(m是4的倍数)。每个窗户要么是明亮的,要么是昏暗的。

每间房间要么是一居室,房间内有一个窗户,要么是两居室,房间内是同一层的连续两个窗户。每一层中,恰好有 m 2 \frac{m}{2} 2m个一居室和 m 4 \frac{m}{4} 4m 个两居室。

对于一间公寓,只要其中有一个窗户是明亮的,则称这间公寓是明亮的。对于所有划分公寓的方法,求明亮的公寓的数量的最大值和最小值。

思路:对每层贪心考虑

最小值:那肯定是尽可能将两个亮的窗户划分成一个大房间(记为c11)

  • c 11 ≤ m 4 c11\le\frac{m}{4} c114m:两居室还有剩余,在这种情况下剩下的1都能够点亮1个房间,答案为 c 11 + c 1 − c 11 ∗ 2 c11+c1-c11*2 c11+c1c112(c1为1的数量)
  • c 11 > m 4 c11>\frac{m}{4} c11>4m:11能够填满所有的两居室,那么剩下的也就都是一居室了,答案为 m 4 + ( c 1 − m 4 ∗ 2 ) \frac{m}{4}+(c1-\frac{m}{4}*2) 4m+(c14m2)

最大值:尽可能不让11划分成两居室,记c00为能划分成非11的最多两居室的数量

  • c 00 ≤ m 4 c00\le\frac{m}{4} c004m:两居室还有剩余,则必须要用11作为两居室划分成剩余的两居室,其余的每个1都能够点亮一个房间,此时答案为 c 1 − ( m 4 − c 00 ) c1-(\frac{m}{4}-c00) c1(4mc00)
  • c 00 > m 4 c00>\frac{m}{4} c00>4m:显然所有的1都能够点亮1个房间,答案为 c 1 c1 c1

详见代码

void solve() {
    cin >> n >> m;
    char a[n + 1][m + 1];
    vector<int> c0(n + 1, 0), c1(n + 1, 0), c00(n + 1, 0), c11(n + 1, 0);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> a[i][j], c1[i] += (a[i][j] == '1');
    int ans1 = 0, ans2 = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < m; j++) {
            if (!(a[i][j] == '1' && a[i][j + 1] == '1'))//计算不把11划分成两居室的数量
                c00[i]++, j++;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < m; j++) {
            if (a[i][j] == '1' && a[i][j + 1] == '1')//计算11的数量
                c11[i]++, j++;
        }
    }
    for (int i = 1; i <= n; i++) {
        int last = c1[i] - 2 * c11[i];
        if (c11[i] <= m / 4) ans1 += c11[i] + last;
        else ans1 += m / 4 + (c1[i] - m / 2);
        if (c00[i] <= m / 4) ans2 += c1[i] - (m / 4 - c00[i]);
        else ans2 += c1[i];

    }
    cout << ans1 << " " << ans2 << "\n";
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

self_disc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值