HDU多校 1、2

G1

D

可以看出,到了>3的情况,只要abcabc循环下去就行。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 5e4+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int t,n;
int main()
{
    t=read();
    while (t--)
    {
        n=read();
        if (n==1) cout<<26<<endl;
        else if (n==2) cout<<676<<endl;
        else if (n==3) cout<<676*26<<endl;
        else cout<<26*25*24%mod<<endl;;
    }
    return 0;
}
View Code

I

这题本意跟栈的处理基本上是相同了,栈模拟即可。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 5e4+10;
const int INF = 0x3f3f3f3f; 
const int mod = 998244353;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
struct node
{
    ll p,a;    
};
ll T,i,n,ans,num;
node b[maxn],s[maxn];
bool cmp(node x,node y)
{
    if (x.a==y.a) return x.p<y.p;
    return x.a<y.a;
}
bool check(node x,node y,node z)
{
    return (y.p-z.p)*(y.a-x.a)-(z.a-y.a)*(x.p-y.p)<=0;
}
int main()
{
    T=read();
    while (T--)
    {
        n=read();
        map<pii , ll> mapp;
        for (i=1;i<=n;i++) 
        {
            b[i].p=read(),b[i].a=read();
            mapp[mp(b[i].p,b[i].a)]++;
        }
        sort(b+1,b+1+n,cmp);
        num=0;
        for (i=1;i<=n;i++)
        {
            while ((num>0 && (b[i].p>=s[num].p)) ||(num>1 && check(s[num-1],s[num],b[i])))
            {
                num--;
            }
            s[++num]=b[i];
        }
        ans=num;
        for (i=1;i<=num;i++)
        {
            if (mapp[mp(s[i].p,s[i].a)]>1) ans--;
        }
        cout<<ans<<endl;
    }
    return 0;
}
//18
//24163 1
//24068 190
//23783 380
//23308 570
//22643 760
//21788 950
//20743 1140
//19508 1330
//18083 1520
//16468 1710
//14663 1900
//12668 2090
//10483 2280
//8108 2470
//5543 2660
//2788 2850
//24168 27
//24172 26
View Code

G2

A

题意就是把连通块进行不断拆分删边,根本没意识到这就是并查集的逆过程……

逆向思维很重要

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1e5+7;
const int INF = 0x3f3f3f3f; 
const int mod = 1e9+7;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
struct node
{
    ll value,num;    
};
vector <ll> G[maxn];
node a[maxn];
ll father[maxn],u,v,i,n,m,t,vis[maxn];
ll sum,block;
bool cmp(node x,node y)
{
    return x.value>y.value;
}
ll fa(ll x)
{    
    return father[x]==x?x:father[x]=fa(father[x]);
}
ll join(ll x, ll y)
{
    x=fa(x),y=fa(y);
    if (x!=y) father[x]=y;
}
int main()
{
    t=read();
    while (t--)
    {
        n=read(),m=read();
        for (i=1;i<=n;i++) father[i]=i,a[i].num=i,a[i].value=read();
        sort(a+1,a+1+n,cmp);
        a[n+1].value=0;
        for (i=1;i<=m;i++) 
        {
            u=read(),v=read();
            G[u].push_back(v);
            G[v].push_back(u);
        }
        for (i=1;i<=n;i++) vis[i]=false;
        sum=block=0;
        for (i=1;i<=n;i++)
        {
            u=a[i].num;
            vis[u]=true;
            block++;
            for (auto v:G[u])
            {
                if (!vis[v]) continue;
                if (fa(v)!=fa(u)) 
                    join(u,v),block--;
            }
            sum+=block*(a[i].value-a[i+1].value);
        }
        for (i=1;i<=n;i++) G[i].clear();
        cout<<sum<<endl;
    }
    return 0;
}
View Code

J

数据很小,暴搜即可。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 55;
const int INF = 0x3f3f3f3f; 
const int mod = 1e9+7;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
struct node
{
    ll a,b,c,d;
};
vector <node> G[maxn];
int i,n,k,vis[maxn],t,x,a,b,c,d;
ll cnt;
ll dfs(ll num,ll a,ll b,ll c,ll d)
{
    if (num==cnt+1)
    {
        return (100+a)*(100+b)*(100+c)*(100+d);
    }
    ll ans=0;
    for (ri i=0;i<G[num].size();i++)
    {
        node now=G[num][i];
        ans=max(ans,dfs(num+1,a+now.a,b+now.b,c+now.c,d+now.d));
    }
    return ans;
}
int main()
{
    t=read();
    while (t--)
    {
        n=read(),k=read();
        cnt=0;
        for (i=1;i<=n;i++) 
        {
            x=read(),a=read(),b=read();
            c=read(),d=read();
            if (!vis[x])
            {
                vis[x]=++cnt;
            }
            G[vis[x]].push_back({a,b,c,d});
        }
        printf("%lld
",dfs(1,0,0,0,0));
        for (i=1;i<=n;i++) G[i].clear(),vis[i]=0;
    }
    return 0;
}
View Code

F

将某一位从1变成0,其实就是从原数中减去那一位的斐波那契数。

然后可以得出下面的式子,假设改变位的下标为k,则有:

A * B = C + Fk

容易得到ABC都是可以O(n)算出来的,最后的Fk暴力枚举也能求出来。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 2e6+7;
const int INF = 0x3f3f3f3f; 
const int mod = 1e9+7;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
ll f[maxn],i,t,x,n,sum1,sum2,sum3;
int main()
{
    f[1]=1,f[2]=2;
    for (i=3;i<=maxn;i++) f[i]=f[i-1]+f[i-2];
    t=read();
    while (t--)
    {
        n=read();
        sum1=sum2=sum3=0;
        for (i=1;i<=n;i++) 
        {
            x=read();
            if (x==1) sum1+=f[i];
        }
        n=read();
        for (i=1;i<=n;i++) 
        {
            x=read();
            if (x==1) sum2+=f[i];
        }
        n=read();
        for (i=1;i<=n;i++) 
        {
            x=read();
            if (x==1) sum3+=f[i];
        }
        for (i=1;i<=maxn;i++)
        {
            if (sum3==sum1*sum2-f[i])
            {
                cout<<i<<endl;
                break;
            }
        }
    }
    return 0;
}
View Code

总结:有些题目很多人过,比如G1的Fibonacci Sum,但是补过很长时间真就是这没学,那不懂,况且我无法保证比赛时能否做的出来这种烧脑的题目,以至于这些数论题就此作罢。

原文地址:https://www.cnblogs.com/Y-Knightqin/p/13440195.html