《多校补题》

前言:高处不胜寒,但贵在坚守。

Divisibility

题解上都是从结论出发去证明的。但我觉得一开始不可能都知道结论。所以稍微从思考角度出发

可以发现$y = c1* b^{n-1} + c2 * b^{n-2} + ... + cn * b^{0}$

那么对于无限的f(y)操作,可以发现每次都是将所有位数加后重构继续加后重构。

那么可以看成对x各位相加后的取模操作。

那么题目就可以转化成:

是否同时满足:

$(c1* b^{n-1} + c2 * b^{n-2} + ... + cn * b^{0}) \equiv 0 mod (x)$时,

也满足 $(c1 + c2 + ... + cn ) \equiv 0 mod (x)$.

可以发现的是b = 1时,满足两式相等,那么肯定性质相同。

即可以发现b mod x == 1时,可以使两式相等,永远满足。

当b mod x != 1时。

证明:

如果b < x,那么显然不行,可以构造一个x的倍数,然后x的倍数最终会被转化到 < x。此时无法满足性质相同。

如果b >= x.令 $y = 0+0+....1*b^{1}+x-1$.

若$b+x-1 \equiv 0 (mod x)$

即$b \equiv 1 (mod x)$

因为b mod x != 1,所以矛盾,无法满足。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 1e5+5;
const int M = 1e6+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline LL read()
{
    LL x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
int main()
{
    int ca;ca = read();
    while(ca--)
    {
        LL b,x;b = read(),x = read();
        if(b%x == 1) printf("T\n");
        else printf("F\n");
    }
    system("pause");
    return 0;
}
View Code

Little Rabbit's Equation

难度最低的一个题吧。(进制转换对我来说还是很难受)

考虑这么多种进制会很难处理,那么将所有数都转化为10进制即可(注意这里最大15位数,所以开longlong)

记一下进制转换:将其他进制转换为10进制,以该进制为基数来模拟10进制+来实现转化。

注意的是,如果当前值>=进制,那么说明这个数不属于这个进制,那么次时查找肯定无效。

PS:printf和cin混用导致debug了蛮久。。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const LL N = 2e14+5;
const int M = 1005;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
unordered_map<char,LL> mp;
void init()
{
    mp['0'] = 0,mp['1'] = 1,mp['2'] = 2,mp['3'] = 3,mp['4'] = 4,mp['5'] = 5;
    mp['6'] = 6,mp['7'] = 7,mp['8'] = 8,mp['9'] = 9,mp['A'] = 10,mp['B'] = 11;
    mp['C'] = 12,mp['D'] = 13,mp['E'] = 14,mp['F'] = 15;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    init();
    string s;
    while(cin >> s)
    {
        int flag = 0;
        for(int ba = 2;ba <= 16;++ba)
        {
            LL a = 0,b = 0,c = 0,t = 0;
            int id,tag = 0;
            for(int i = 0;i < s.size();++i)
            {
                if(s[i] == '+') a = t,t = 0,id = 1;
                else if(s[i] == '-') a = t,t = 0,id = 2;
                else if(s[i] == '*') a = t,t = 0,id = 3;
                else if(s[i] == '/') a = t,t = 0,id = 4;
                else if(s[i] == '=') b = t,t = 0;
                else 
                {
                    if(mp[s[i]] >= ba){tag = 1;break;}
                    t = t*ba+mp[s[i]];
                }
            }
            if(tag) continue;
            c = t;
           // printf("a is %lld b is %lld c is %lld\n",a,b,c);
            if(id == 1 && a+b == c) flag = ba;
            if(id == 2 && a-b == c) flag = ba;
            if(id == 3 && a*b == c) flag = ba;
            if(id == 4 && b*c == a) flag = ba;
            if(flag) break;
        }
        if(flag) cout << flag << endl;
        else cout << "-1" << endl;
    }
    system("pause");
    return 0;
}
View Code

Road To The 3rd Building

可以发现的是,对于长度一样的组合,他们的长度是一样的。

那么记录下前缀和即可。

这里由于取模后sum[n-i+1]可能会<sum[i-1],所以要加模数防负数。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 2e5+5;
const int M = 1e6+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline LL read()
{
    LL x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
LL quick_mi(LL a,LL b)
{
    LL re = 1;
    a %= Mod;
    while(b)
    {
        if(b&1) re = (re*a)%Mod;
        a = (a*a)%Mod;
        b >>= 1;
    }
    return re;
}
LL sum[N],a[N];
int main()
{
    int ca;ca = read();
    while(ca--)
    {
        LL n;n = read();
        memset(sum,0,sizeof(sum));
        for(int i = 1;i <= n;++i) a[i] = read(),sum[i] = (sum[i-1]+a[i])%Mod;
        LL ans = 0,pre = 0;
        for(int i = 1;i <= n/2;++i)
        {
            pre = (pre+(sum[n-i+1]-sum[i-1])%Mod+Mod)%Mod;
            ans = (ans+pre*quick_mi(i,Mod-2)%Mod)%Mod;
            ans = (ans+pre*quick_mi(n-i+1,Mod-2)%Mod)%Mod;
        }
        if(n%2 == 1)
        {
            pre = (pre+a[n/2+1])%Mod;
            ans = (ans+pre*quick_mi(n/2+1,Mod-2)%Mod)%Mod;
        }
        LL ma = n*(n+1)/2;
        ans = ans*quick_mi(ma,Mod-2)%Mod;
        printf("%lld\n",ans);
    }
    system("pause");
    return 0;
}
View Code

A Very Easy Graph Problem

递推了一个小时终于递推出了(i,j)可轮换的换根dp的转移式。

结果一看题不可轮换,人傻了。。(先记录一下,毕竟是努力的结果)

可轮换代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 1e5+5;
const int M = 1e6+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read()
{
    int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
struct Node{int to;LL dis;};
vector<Node> G[N];
int n,m,a[N],fa[N];
LL dp[N][2],num[N][2],cnt1 = 0,cnt0 = 0;//num[2][0]-向下有多少0点,num[2][1]-1点,dp[2][0]向下的0的距离总和,dp[2][1]向下的1距离总和
int Find(int x)
{
    return x == fa[x] ? x : fa[x] = Find(fa[x]);
}
LL quick_mi(LL a,LL b)
{
    LL re = 1;
    a %= Mod;
    while(b)
    {
        if(b&1) re = (re*a)%Mod;
        a = (a*a)%Mod;
        b >>= 1;
    }
    return re;
}
LL inv(LL n){return quick_mi(n,Mod-2)%Mod;}
void dfs(int u,int fa)
{
    if(a[u] == 1) num[u][1] = 1;
    else num[u][0] = 1;
    for(auto v : G[u])
    {
        if(v.to == fa) continue;
        dfs(v.to,u);
        num[u][0] += num[v.to][0];
        num[u][0] %= Mod;
        num[u][1] += num[v.to][1];
        num[u][1] %= Mod;
        dp[u][0] = (dp[u][0]+dp[v.to][0]+(num[v.to][0]*v.dis)%Mod)%Mod;
        dp[u][1] = (dp[u][1]+dp[v.to][1]+(num[v.to][1]*v.dis)%Mod)%Mod;
    }
}
void dfs1(int u,int fa,LL dis)
{
    if(fa != 0)
    {
        dp[u][1] = (dp[u][1]+((dp[fa][1]-dp[u][1]-num[u][1]*dis%Mod)+Mod)%Mod+((cnt1-num[u][1])+Mod)%Mod*dis%Mod)%Mod;
        dp[u][1] = (dp[u][1]+Mod)%Mod;
        dp[u][0] = (dp[u][0]+((dp[fa][0]-dp[u][0]-num[u][0]*dis%Mod)+Mod)%Mod+((cnt0-num[u][0])+Mod)%Mod*dis%Mod)%Mod;
        dp[u][0] = (dp[u][0]+Mod)%Mod;
    }
    for(auto v : G[u])
    {
        if(v.to == fa) continue;
        dfs1(v.to,u,v.dis);
    }
}
int main()
{
    int t;t = read();
    while(t--)
    {
        n = read(),m = read();
        memset(dp,0,sizeof(dp));
        memset(num,0,sizeof(num));
        cnt1 = cnt0 = 0;
        for(int i = 1;i <= n;++i) 
        {
            a[i] = read(),G[i].clear(),fa[i] = i;
            if(a[i] == 1) cnt1++;
            else cnt0++;
        }
        for(int i = 1;i <= m;++i)
        {
            int u,v;u = read(),v = read();
            int xx = Find(u),yy = Find(v);
            if(xx != yy)
            {
                fa[xx] = yy;
                G[u].push_back(Node{v,quick_mi(2,i)});
                G[v].push_back(Node{u,quick_mi(2,i)});
            }
        }
        dfs(1,0);
        dfs1(1,0,0);
        LL ans = 0;
        for(int i = 1;i <= n;++i) printf("i is %d 0 is %lld 1 is %lld\n",i,dp[i][0],dp[i][1]);
        for(int i = 1;i <= n;++i) ans = (ans+dp[i][a[i]^1])%Mod;
        printf("%lld\n",ans);
    }
    system("pause");
    return 0;
}
View Code

 正解:

可以发现,这个图并不是一个树。

但是,我们要的距离是最短距离,那么可以在输入的时候去维护一棵最小的生成树。

因为满足$2^{i} > 2^{i-1} + 2^{i-2} + ... 2^{1}$

那么我们选择越前面的边,显然代价越小。

那么就可以维护输入顺序的最小生成树即可。

如何统计答案,因为是不可轮换式的。

那么我们可以去统计每条边对答案的贡献。

所以我们dfs处理出每个点下面的0,1的数量(包括该点)。

然后对于一条边的贡献就是他一边的1的数量*另一边的0的数量*该边的权值 (即num1 * num0 * cost)  .还有 0 * 1 * cost

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 1e5+5;
const int M = 1e6+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read()
{
    int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
struct Node{int to;LL dis;};
vector<Node> G[N];
int n,m,a[N],fa[N];
LL num[N][2],ans,cnt1,cnt0;
int Find(int x)
{
    return x == fa[x] ? x : fa[x] = Find(fa[x]);
}
LL quick_mi(LL a,LL b)
{
    LL re = 1;
    while(b)
    {
        if(b&1) re = (re*a)%Mod;
        a = (a*a)%Mod;
        b >>= 1;
    }
    return re;
}
void dfs(int u,int fa)
{
    num[u][a[u]] = 1;
    for(auto v : G[u])
    {
        if(v.to == fa) continue;
        dfs(v.to,u);
        num[u][0] += num[v.to][0];
        num[u][0] %= Mod;
        num[u][1] += num[v.to][1];
        num[u][1] %= Mod;
    }
}
void dfs1(int u,int fa,LL dis)
{
    if(fa != 0)
    {
        ans = (ans+dis*((num[u][0])*(cnt1-num[u][1])%Mod)%Mod)%Mod;
        ans = (ans+dis*((num[u][1])*(cnt0-num[u][0])%Mod)%Mod)%Mod;
    }
    for(auto v : G[u])
    {
        if(v.to == fa) continue;
        dfs1(v.to,u,v.dis);
    }
}
int main()
{
    int t;t = read();
    while(t--)
    {
        n = read(),m = read();
        memset(num,0,sizeof(num));
        ans = cnt1 = cnt0 = 0;
        for(int i = 1;i <= n;++i) 
        {
            a[i] = read(),G[i].clear(),fa[i] = i;
            if(a[i] == 1) cnt1++;
            else cnt0++;
        }
        for(int i = 1;i <= m;++i)
        {
            int u,v;u = read(),v = read();
            int xx = Find(u),yy = Find(v);
            if(xx != yy)
            {
                fa[xx] = yy;
                G[u].push_back(Node{v,quick_mi(2,i)});
                G[v].push_back(Node{u,quick_mi(2,i)});
            }
        }
        dfs(1,0);
        dfs1(1,0,0);
        printf("%lld\n",ans);
    }
    system("pause");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zwjzwj/p/13452343.html