牛客网多校第四场

A:Ternary String

扩展欧拉降幂,维护不同模phi下的ans,观察可得后面一堆phi是2的倍数,当指数很大时取模都是1,所以只要维护8层phi就好了

B:Interval Revisited

⼀一个显然的结论:每个位置最多被两个区间覆盖

•所有区间按照右端点从小到大排序

•dp(i, j)表示第i个区间必选,上⼀一次被覆盖⼀一次的位置是j,[1, j]覆盖权值和最⼤大值 的最小值

•dp(i, j) = min(max(dp(k, l), w(i) + w(k)) R(k) +1 >= L(i) and L(k) -1 <= l < L(i) •j和R(k)有关

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
struct node
{
    int le,ri,wi;
};
node seg[2010];
int n,m;
int dp[2010][2010];

void init()
{
    memset(dp,0x3f,sizeof(dp));
}

bool cmp(const node &a,const node &b)
{
    if(a.ri==b.ri) return a.wi<b.wi;
    return a.ri<b.ri;
}

int main()
{
    int i,j;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
        {
            scanf("%d%d%d",&seg[i].le,&seg[i].ri,&seg[i].wi);
        }
        init();
        sort(seg+1,seg+1+n,cmp);

        int ans=dp[0][0];
        for(i=1;i<=n;i++)
        {
            if(seg[i].le==1) dp[i][0]=seg[i].wi;
            for(j=1;j<=i;j++)
            {
                if(seg[j].ri<seg[i].le-1) continue;
                int maxx=dp[j][seg[i].le-1];
                if (seg[j].ri>=seg[i].le) maxx=max(maxx,seg[i].wi+seg[j].wi);
                else maxx=max(maxx,max(seg[i].wi,seg[j].wi));
                dp[i][seg[j].ri]=min(dp[i][seg[j].ri],maxx);
            }
            for(j=seg[i].le;j<=seg[i].ri;j++)
            {
                dp[i][j]=min(dp[i][j],dp[i][j-1]);
            }
            if(seg[i].ri==m) ans=min(ans,dp[i][m]);
        }
        if(ans==0x3f3f3f3f) ans=-1;
        printf("%d\n",ans);
    }
    return 0;
}
View Code

C:Chiaki Sequence Reloaded

这题主要是结论难得找,找到结论后就是一个数位DP板题了

扫描二维码关注公众号,回复: 2489045 查看本文章
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
const long long mod=1e9+7;
long long n;
long long dp[70][150][4];
int num[70],len;


//pre表示上一个填的啥,pre=0表示还没填任何数(没出现第一个1).
//state表示相邻对有多少相同和不同,因为可能为负,所以加上偏移量66
long long dfs(int pos,int state,int lim,int pre)
{
   // cout<<pos<<" "<<state<<endl;
    if(pos==-1) return abs(state-66);
    if(!lim&&dp[pos][state][pre]!=-1) return dp[pos][state][pre];
    int up=lim?num[pos]:1;
    long long cnt=0;
    for(int i=0;i<=up;i++)
    {
        if(pre==2)
        {
            if(i==1) cnt+=dfs(pos-1,state,lim&&i==up,i);
            else cnt+=dfs(pos-1,state,lim&&i==up,pre);
        }
        else cnt+=dfs(pos-1,state+(i==pre?1:-1),lim&&i==up,i);
    }
    cnt%=mod;
    if(!lim) dp[pos][state][pre]=cnt;
    return cnt;
}

long long solve(long long a)
{
    len=0;
    while(a>0)
    {
        num[len++]=a%2;
        a/=2;
    }
    return dfs(len-1,66,1,2);
}

int main()
{
    int T;
    memset(dp,-1,sizeof(dp));
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&n);
        printf("%lld\n",solve(n));
    }
    return 0;
}
View Code

D:Another Distinct Values

F:Beautiful Garden

G:Maximum Mode

H:Double Palindrome

J:Hash Function

猜你喜欢

转载自www.cnblogs.com/Hetui/p/9397861.html