比赛链接

难度递增:FDABEC

A

枚举中间隔板的位置,然后分别枚举左右隔板,找到最大值。时间复杂度

//赛时代码 by zys
#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int maxn=5010;
int n;
int a[maxn];
int ans;
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(int i=2;i<n;i++)
    {
        int ansl=0;
        int ansr=0;
        for(int l=1;l<i;l++)
        {
            ansl=max(ansl,(i-l)*min(a[l],a[i]));
        }
        for(int r=i+1;r<=n;r++)
        {
            ansr=max(ansr,(r-i)*min(a[i],a[r]));
        }
        ans=max(ans,ansl+ansr);
    }
    cout<<ans;
    return 0;
}

B

容易发现任意五局形成 00111 的概率为

长度为 的字符串有 个长度为 的子串,每个字串形成 00111 的概率都是上述值,于是答案就是 。要特判 的情况。

//赛时代码 by fqr
#include<bits/stdc++.h>
using namespace std;
#define endl '\n' 
#define int long long
namespace Main
{
    const int p = 1e9 + 7;
    int qpow(int a,int k)
    {
        int res=1;
        while(k)
        {
            if(k&1)
                res = res * a % p;
            k >>= 1;
            a = a * a % p;
        }
        return res;
    }
    int a, b, n;
    int pwin, plose, p1;
    void solve()
    {
        cin >> a >> b >> n;
        if(n<=4)
            return cout << 0 << endl, void();
        pwin = a * qpow(b, p - 2) % p, plose = (1 - pwin + p) % p;
        p1 = qpow(plose, 2) * qpow(pwin, 3) % p;
        cout << p1 * (n - 4) % p << endl;
    }
     
    void main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
        int _;cin>>_;while(_--) solve();
    }
};
 
signed main()
{
    Main::main();
    return 0;
}

C

zys 通过打表发现,,比较类似于斐波那契数列的性质。

于是考虑枚举 ,求 个数。

zyz 赛时用欧拉函数求的,下面是一个更简单的做法:

个数为 。则 可以表示为:

( 的公约数的 个数 ) ( 的个数 )。

则上述式子可以表示为 。倒着递推即可。时间复杂度

最终答案即为

//赛时代码 by zyz
# include <bits/stdc++.h>
 
using namespace std;
 
const int N = 3e6 + 5 , mod = 1e9 + 7;
int n , f[N] , primes[N] , phi[N] , vis[N] , pcnt , ans;
 
void init()
{
    vis[1] = 1;
    phi[1] = 1;
    for(int i = 2; i <= n; i++)
    {
        if(!vis[i]) phi[i] = i - 1 , primes[++pcnt] = i;
        for(int j = 1; j <= pcnt && i * primes[j] <= n; j++)
        {
            vis[i * primes[j]] = 1;
            if(i % primes[j] == 0) 
            {
                phi[i * primes[j]] = 1ll * phi[i] * primes[j] % mod;
                break ;
            }
            phi[i * primes[j]] = 1ll * phi[i] * phi[primes[j]] % mod;
        }
    }
    for(int i = 2; i <= n; i++) phi[i] = (1ll * phi[i - 1] + phi[i]) % mod;
}
 
 
int main()
{
    cin >> n;
    init();
    f[0] = 0 , f[1] = 1;
    for(int i = 2; i <= n; i++) f[i] = (3ll * f[i - 1] % mod + 2ll * f[i - 2] % mod) % mod;
    for(int i = 1; i <= n; i++)
    {
        ans = (ans + 1ll * f[i] * (2ll * phi[n / i] % mod - 1 + mod) % mod) % mod;
    }
    cout << ans;
    return 0;
}
//赛后代码 by fqr
#include<bits/stdc++.h>
using namespace std;
#define int long long

namespace Main
{
    const int N = 3000010, p = 1e9 + 7;
    int n;
    int f[N], F[N];
    void main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
        cin >> n;
        F[0] = 0, F[1] = 1;
        for (int i = 2; i <= n; i++)
            F[i] = (3 * F[i - 1] % p + 2 * F[i - 2] % p) % p;
        int ans = 0;
        for (int i = n; i >= 1; i--)
        {
            f[i] = (n / i) * (n / i) % p;
            for (int j = i + i; j <= n; j += i)
                f[i] = ((f[i] - f[j]) % p + p) % p;
            ans += f[i] * F[i] % p, ans %= p;
        }
        cout << ans;
    }
};

signed main()
{
    Main::main();
    return 0;
}

D

容易发现某个数除以 可以得到所有胜率,于是场数 ,两层循环暴力枚举即可。

//赛时代码 by zys
#include<bits/stdc++.h>
using namespace std;
int main()
{
    double a;
    cin>>a;
    for(double i=1;i<=10000;i++)
    for(double j=1;j<=i;j++)
    {
        if(abs(100.0*j/i-a)<=0.005) 
        {
            cout<<i;
            return 0;
        }
    }
    return 0;
}

E

引理 1:双方每次取的石子数量都是奇数。

证明: = ,易证 是偶数,所以原式是奇数。

引理 2:谁取到最后一个石子,谁就获胜。

证明:当 时,两方都可以取 个石子,所以只有当没有石子时会失败,于是谁取到最后一个石子,谁就获胜。

由引理 1 可知,每次取完石子,剩余数量的奇偶性都会改变。由引理 2 可知,游戏结束时,石子数量为 ,是偶数。

因此若 为奇数先手胜,否则后手胜。

//赛时代码 by fqr
#include<bits/stdc++.h>
using namespace std;
#define endl '\n' 
 
namespace Main
{
    void solve()
    {
        int a, b, n;
        cin >> a >> b >> n;
        cout << (n % 2 == 1 ? "Alice" : "Bob") << endl;
    }
     
    void main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
        int _;cin>>_;while(_--) solve();
    }
};
 
int main()
{
    Main::main();
    return 0;
}

F

经过两位数减法可知,答案为

//赛时整活代码 by zys
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int ans=0;
    for(int i=1;i<=27;i++)
    {
        ans++;
    }
    cout<<ans<<endl;
    return 0;
}