2020杭电多校第六场 解题报告1001 1002 1006 1009

1001 - Road To The 3rd Building

题意

  • 任取i,j,其中1<=i<=j<=n
  • \sum _{k=i}^j \frac{a_k}{j-i+1}的期望

思路 

  • 手写几个找出规律

举个栗子,n=5。可爱度:1 3 2 5 7

以下的12345指的是位置。

长度为1:1  2  3  4  5

长度为2:12  23  34  45

长度为3:123  234  345 

长度为4:1234  2345

长度为5:12345

 期望就是\frac{1+3+2+5+7+\frac{1+3}{2}+\frac{3+2}{2}+\frac{3+2}{2}+\frac{5+7}{2}+\frac{1+3+2}{3}+\frac{3+2+5}{3}+\frac{2+5+7}{3}+\frac{1+3+2+5}{4}+\frac{3+2+5+7}{4}+\frac{1+3+2+5+7}{5}}{15}

将其拆开:

1号位置乘的数分别是1           \frac{1}{2}            \frac{1}{3}          \frac{1}{4}          \frac{1}{5}

2号位置乘的数分别是1           \frac{1}{2}*2      \frac{1}{3}*2    \frac{1}{4}*2   \frac{1}{5}

3号位置乘的数分别是1          \frac{1}{2}*2      \frac{1}{3}*3    \frac{1}{4}*2   \frac{1}{5}

4号位置乘的数分别是1          \frac{1}{2}*2      \frac{1}{3}*2    \frac{1}{4}*2   \frac{1}{5}

5号位置乘的数分别是1           \frac{1}{2}            \frac{1}{3}          \frac{1}{4}          \frac{1}{5}

将其系数提出来发现:

 

1号位置乘的数分别是1          1            1           1          1

2号位置乘的数分别是1          2            2           2          1

3号位置乘的数分别是1          2            3           2          1

4号位置乘的数分别是1          2            2           2          1

5号位置乘的数分别是1          1            1           1          1

  • 有这个规律就很好算了,先预处理出1 2 3 4 ... n的逆元
  • sum是1到n的逆元之和
  • cal在第一行是sum,第二行就减去首尾两个逆元
  • ss是第一行的总值
  • 最后累加计算ss*(s[i]+s[n+1-i]) (1<=i<=n/2)(s[i]是可爱度,由于上下是对称的,可以同时运算)
  • 如果n是奇数,那么会多出一行,再加上s[n/2+1]*ss就好

AC代码

#include <bits/stdc++.h>
#define LL long long
#define sc(a) scanf("%d", &a)
#define sc2(a, b) scanf("%d%d", &a, &b)
#define sc3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define scl(a) scanf("%lld", &a)
#define scl2(a, b) scanf("%lld%lld", &a, &b)
#define ss(a) scanf("%s", a)
#define mem(a, b) memset(a, b, sizeof(a))
#define PII pair<int, int>
using namespace std;
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
LL s[maxn];
LL k[maxn];
LL POW(LL a, LL b)
{
    a%=mod;b%=mod;
    LL ans = 1;
    while (b)
    {
        if (b & 1)ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
LL inv(LL b)
{
    return POW(b, mod - 2);
}
int main()
{
    for(int i=1;i<maxn;i++){
        k[i]=inv(i);
    }
    int t;sc(t);
    while(t--){
        LL n;scl(n);
        LL p=inv(n*(n+1)/2);
        LL sum=0;
        for(int i=1;i<=n;i++)sum=(sum+k[i])%mod;
        for(int i=1;i<=n;i++)scl(s[i]);
        LL ans=0,cal=sum,ss=sum;
        for(int i=1;i<=n/2;i++){
            ans=(ans+(s[i]+s[n+1-i])%mod*ss%mod)%mod;
            cal=(cal-k[i]+mod)%mod;
            cal=(cal-k[n+1-i]+mod)%mod;
            ss=(ss+cal)%mod;
        }
        if(n&1){
            ans=(ans+s[n/2+1]*ss%mod)%mod;
        }
        cout<<ans*p%mod<<endl;
    }
    system("pause");
    return 0;
}

1002 - Little Rabbit's Equation

题意

  • 给一个等式,问你该等式在几进制的情况下成立,有的话输出进制最小的情况,没有的话输出-1
  • 进制的范围时2~16

思路

  • 数据不大,直接枚举2到16进制就可
  • 注意每个数都要小于枚举的进制
  • 注意要取出的数要开long long

AC代码

#include <bits/stdc++.h>
#define LL long long
#define sc(a) scanf("%d", &a)
#define sc2(a, b) scanf("%d%d", &a, &b)
#define sc3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define scl(a) scanf("%lld", &a)
#define scl2(a, b) scanf("%lld%lld", &a, &b)
#define ss(a) scanf("%s", a)
#define mem(a, b) memset(a, b, sizeof(a))
#define PII pair<int, int>
using namespace std;
const int maxn = 5e5 + 5;
const int mod = 1e9 + 7;
bool ok(char a)//判断运算符
{
    return a == '+' || a == '-' || a == '*' || a == '/' || a == '=';
}
LL cal(LL a, LL b, char op)//计算
{
    if (op == '+')
        return a + b;
    if (op == '-')
        return a - b;
    if (op == '*')
        return a * b;
}
int main()
{
    string a;
    while (cin >> a)
    {
        vector<string> v;      //存放运算数
        vector<LL> b1, b2, b3; //存放运算数每位的十进制形式
        int j = 0;
        for (int i = 0; i < a.size(); i++)
        {
            if (ok(a[i]))
            {
                v.push_back(a.substr(j, i - j)); //取出计算数
                j = i + 1;
            }
        }
        v.push_back(a.substr(j)); //最后一个运算数

        string b = v[0];
        for (int i = 0; i < b.size(); i++)
        {
            if (b[i] >= 'A')
                b1.push_back(b[i] - 'A' + 10);
            else
                b1.push_back(b[i] - '0');
        }
        b = v[1];
        for (int i = 0; i < b.size(); i++)
        {
            if (b[i] >= 'A')
                b2.push_back(b[i] - 'A' + 10);
            else
                b2.push_back(b[i] - '0');
        }
        b = v[2];
        for (int i = 0; i < b.size(); i++)
        {
            if (b[i] >= 'A')
                b3.push_back(b[i] - 'A' + 10);
            else
                b3.push_back(b[i] - '0');
        }

        int f = 1;
        LL num1, num2, num3;
        char op = a[v[0].size()];     //运算符
        for (int i = 2; i <= 16; i++) //枚举进制
        {
            num1 = 0;
            num2 = 0;
            num3 = 0;
            int fff = 0;
            for (auto j : b1)
            {
                if (j >= i)
                { //当前数应该低于进制数,不然不符合规范
                    fff = 1;
                    break;
                }
                num1 = num1 * i + j;
            }
            for (auto j : b2)
            {
                if (j >= i)
                {
                    fff = 1;
                    break;
                }
                num2 = num2 * i + j;
            }
            for (auto j : b3)
            {
                if (j >= i)
                {
                    fff = 1;
                    break;
                }
                num3 = num3 * i + j;
            }
            if (fff)
                continue;
            if (op != '/')
            {
                LL num = cal(num1, num2, op);
                if (num != num3)
                    continue;
                cout << i << endl;
                f = 0;
                break;
            }
            else
            { //除法运算改乘法运算,避免失精度
                if (num3 * num2 != num1)
                    continue;
                cout << i << endl;
                f = 0;
                break;
            }
        }
        if (f)
            cout << "-1" << endl;
    }
    system("pause");
    return 0;
}

1006 - A Very Easy Graph Problem

题意

对于任意b进制正整数y=\overline{c_1c_2...c_n},如果c_1+c_2+...+c_n\equiv(0 mod x),那么y\equiv(0 mod x),否则y \not\equiv0 (mod x)

判断对于给定的b和x,该命题是否成立。

思路

该命题仅在b\equiv1 (mod x)情况下成立,即b%x=1

证明如下:

AC代码

#include <bits/stdc++.h>
#define LL long long
#define sc(a) scanf("%d", &a)
#define sc2(a, b) scanf("%d%d", &a, &b)
#define sc3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define scl(a) scanf("%lld", &a)
#define scl2(a, b) scanf("%lld%lld", &a, &b)
#define ss(a) scanf("%s", a)
#define mem(a, b) memset(a, b, sizeof(a))
#define PII pair<int, int>
using namespace std;
const int maxn = 5e5 + 5;
const int mod = 1e9 + 7;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        LL n,k;
        scanf("%lld %lld",&n,&k);
        if(n%k==1)
            printf("T\n");
        else
            printf("F\n");
    }

    system("pause");
    return 0;
}

1009 - Divisibility

题意

思路

AC代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值