牛客练习赛 60(待补E-长链剖分或者dsu)

A.大吉大利

位运算有独立性,按位计算对答案的贡献即可。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1000010;
int cnt[40],n;
ll a[N];
int main()
{
    
    
    IO;
    int T=1;
    //cin>>T;
    while(T--)
    {
    
    
        cin>>n;
        for(int i=1;i<=n;i++)
        {
    
    
            cin>>a[i];
            for(int j=0;j<30;j++)
                if(a[i]>>j&1) cnt[j]++;
        }
        ll res=0;
        for(int i=1;i<=n;i++)
        {
    
    
            for(int j=0;j<30;j++)
                if(a[i]>>j&1) res+=(1ll<<j)*cnt[j];
        }
        cout<<res<<'\n';       
    }
    return 0;
}

B.三角形周长和

不难分析出一条边会被 n − 2 n-2 n2个三角形公用,因此求出任意两点的曼哈顿路径✖ ( n − 2 ) (n-2) (n2)即可得出所有三角形周长和,过程中取模即可。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int,int> pii;
const int N=1010;
pii p[N];
int n;
int main()
{
    
    
    IO;
    int T=1;
    //cin>>T;
    while(T--)
    {
    
    
        cin>>n;
        for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y;
        ll res=0;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
            {
    
    
                ll dx=abs(p[i].x-p[j].x);
                ll dy=abs(p[i].y-p[j].y);
                res=(res+dx+dy)%mod;
            }
        res=res*(n-2)%mod;
        cout<<res<<'\n';
       
    }
    return 0;
}

C.操作集锦

菜菜不会啊啊啊
大佬题解
状态表示: f ( i , j ) f_{(i,j)} f(i,j)表示考虑前 i i i个字符,长度是 j j j的不重复子序列的个数
状态转移:对于第 i i i个字符,有两种选择,如果不选择方案数是 f ( i − 1 , j ) f_{(i-1,j)} f(i1,j),如果选择方案数是 f ( i − 1 , j − 1 ) − f ( k − 1 , j − 1 ) f_{(i-1,j-1)}-f_{(k-1,j-1)} f(i1,j1)f(k1,j1) k k k是在 i i i之前最后一次 s i s_i si出现的位置
看了这个方法越想越觉得妙,所以所以我不想啦hhhh

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1010;
const ll mod=1e9+7;
ll f[N][N];
int pre[30];
int n,m;
char s[N];
int main()
{
    
    
    IO;
    int T=1;
    //cin>>T;
    while(T--)
    {
    
    
        cin>>n>>m;
        cin>>s+1;
        for(int i=0;i<=n;i++) f[i][0]=1;
        for(int i=1;i<=n;i++)
        {
    
    
            for(int j=1;j<=i;j++)
            {
    
    
                f[i][j]=f[i-1][j]+f[i-1][j-1];
                if(pre[s[i]-'a']) f[i][j]-=f[pre[s[i]-'a']-1][j-1];
                f[i][j]%=mod;
            }
            pre[s[i]-'a']=i;
        }
        cout<<(f[n][m]%mod+mod)%mod<<'\n';
    }
    return 0;
}

还有一种序列自动机的做法,没学过,回来补一下。
学习序列自动机了,发现上述dp是显然的,我还是见的题太少了~~刷着题补着吧

状态表示: f ( i , j ) f_{(i,j)} f(i,j)表示以 i i i结尾的子序列并且长度是 j j j
状态转移:借助序列自动机找出第一次出现的子序列

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1010;
const ll mod=1e9+7;
ll f[N][N];
int ne[N][30];
int n,m;
char s[N];
int main()
{
    
    
    IO;
    int T=1;
    //cin>>T;
    while(T--)
    {
    
    
        cin>>n>>m;
        cin>>s+1;
        for(int i=n;i;i--)
        {
    
    
            for(int j=0;j<26;j++)
                ne[i-1][j]=ne[i][j];
            ne[i-1][s[i]-'a']=i;
        }
        f[0][0]=1;
        for(int i=0;i<=n;i++)
            for(int j=0;j<=min(m,i);j++)
                for(int k=0;k<26;k++)
                    if(ne[i][k])    
                        f[ne[i][k]][j+1]=(f[ne[i][k]][j+1]+f[i][j])%mod;
        ll res=0;
        for(int i=m;i<=n;i++) res=(res+f[i][m])%mod;
        cout<<res<<'\n';
    }
    return 0;
}

D.斩杀线计算大师

根据扩展欧几里得算法很容易求出 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b),由于本题需要求 a x + b y + c z = k ax+by+cz=k ax+by+cz=k考虑枚举 z z z,那么问题就转化为对于 a x + b y = k − c z ax+by=k-cz ax+by=kcz对于 x , y x,y x,y是否有非负整数解。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    
    
    if(b==0)
    {
    
    
        x=1,y=0;
        return a;
    }
    ll d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
int main()
{
    
    
    IO;
    int T=1;
    //cin>>T;
    while(T--)
    {
    
    
        ll a,b,c,k;
        cin>>a>>b>>c>>k;
        for(int z=0;z*c<=k;z++)
        {
    
    
            ll x,y;
            ll d=exgcd(a,b,x,y);
            if((k-z*c)%d==0)
            {
    
    
                ll gcd=b/d;
                x=((k-z*c)/d*x%gcd+gcd)%gcd;
                y=(k-z*c-x*a)/b;
                if(x>=0&&y>=0) 
                {
    
    
                    cout<<x<<' '<<y<<' '<<z<<'\n';
                    break;
                }
            }
        }
    }
    return 0;
}

E.旗鼓相当的对手

感觉最近有的浮躁,找了几首轻音乐希望能够让我浮躁的心平静下来,而且最近学校破事贼多,人快无了。
要加油哦~

猜你喜欢

转载自blog.csdn.net/Fighting_Peter/article/details/108753394