day5下

t1
一开始提都没弄懂
长度为 n 的置换可以⽤⼀些更短的轮换的乘积来表⽰。
轮换可以⽤ (a,b,c) 形式来表⽰,表⽰ a 变成 b,b 变成 c,c 变成 a。
⽐如 (1,2,3,4) -> (2,3,4,1) 可以表⽰为 (1,2,3,4),也可以表⽰为 (4 1)*
(3 1)* (2 1) 。
轮换的乘积是从右到左进⾏。
现在给你 p 个长度⼩于等于 k 的轮换,他们表⽰的是长度为 n 的置换,
求他们的乘积的置换。
暴力模拟

#include<cstdio>
#include<algorithm>
#define ll long long
#define M 110000
int a[1001],k,n,m,id[1199],x[1199],y[1100][1100];
int main(){
    freopen("rotate.in","r",stdin);
    freopen("rotate.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++) a[i]=i,id[i]=i;
    for(int i=m;i>=1;i--)
    {
        scanf("%d",&x[i]);for(int j=1;j<=x[i];j++)scanf("%d",&y[i][j]); 
    }
    for(int i=1;i<=m;i++)
    {
        int tmp=id[y[i][x[i]]];
        //int tmp2=id[y[i][1]];
        for(int j=x[i];j>1;j--)
        {
            id[y[i][j]]=id[y[i][j-1]];
            //id[y[i][j]]=id[y[i][j+1]];
        }
        id[y[i][1]]=tmp;
        //id[y[i][x[i]]]=tmp2;
    }
    for(int i=1;i<=n;i++) a[id[i]]=i;
    for(int i=1;i<=n;i++) printf("%d ",a[i]);
}

t2
给⼀个长度为 n 的序列 S,以及四个数 a,b,c,d,询问满⾜ a ≤ (S L and S L+1 and … and S R ) ≤
b 且 c ≤ (S L or S L+1 or … or S R ) ≤ d 的区间有多少个。
and、or 为位运算的与和或。
为了避免 64 位整数输出,请将答案对 10 9 + 7 取模。

预处理,打个st表,因为是单调的,&递减,|递增,然后倍增出第一个符合条件的,记下来,在倍增出最后一个
加进答案
垃圾倍增。。。
调了接近一下午终于对了
之前想错了。。。
还有跳过头的没考虑。
我是跳到第一个不行的。判断是n+1

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
int st[110000][20],st2[110000][20],ans;
int n,a,b,c,d;
int main() {
    freopen("range.in","r",stdin);
    freopen("range.out","w",stdout);
    scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
    for(int i=1;i<=n;i++) scanf("%d",&st[i][0]),st2[i][0]=st[i][0];
    for(int k=1;k<=18;k++)
    for(int i=1;i<=n;i++)
    {
        if(i+(1<<k-1)<=n)

            st[i][k]=st[i][k-1]&st[i+(1<<k-1)][k-1]
            ,st2[i][k]=st2[i][k-1]|st2[i+(1<<k-1)][k-1];
        else st[i][k]=st[i][k-1],st2[i][k]=st2[i][k-1];
    }

    for(int i=1;i<=n;i++)
    {
        int tmp=i,tmp2,s=(1<<19)-1,s2=0;

        if(st[i][0]<a||st2[i][0]>d) continue;

        for(int k=18;k>=0;k--)
        if(tmp+(1<<k)-1<=n)
        if(((st[tmp][k]&s)>b)||((st2[tmp][k]|s2)<c)) s&=st[tmp][k],s2|=st2[tmp][k],tmp+=(1<<k);
        tmp2=tmp;

        for(int k=18;k>=0;k--)
        if(tmp+(1<<k)-1<=n)
        if(((st[tmp][k]&s)>=a)&&((st2[tmp][k]|s2)<=d)) s&=st[tmp][k],s2|=st2[tmp][k],tmp+=(1<<k);
        tmp--;
        if(tmp-tmp2+1>0)
        ans=(1ll*ans+tmp-tmp2+1)%1000000007;
    }
    printf("%d",ans);
}

还有暴力,水过

#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const int mod=1e9+7;
int ana[110000][21],ord[110000][21];
int q[110000]; 
int get_and(int l,int r)
{
    int len=(r-l)+1;
    int t=log2(len);
    return ana[l][t]&ana[r-(1<<t)+1][t]; 
}
int get_or(int l,int r)
{
    int len=(r-l)+1;
    int t=log2(len);
    return ord[l][t]|ord[r-(1<<t)+1][t]; 
}
int main()
{
    freopen("range.in","r",stdin);
    //freopen("range.out","w",stdout);
    int n,a,b,c,d;
    scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
    for(int i=1;i<=n;i++)
     scanf("%d",&q[i]),ana[i][0]=q[i],ord[i][0]=q[i];

    for(int j=1;j<=20;j++)
     for(int i=1;i<=n;i++)
      if(i+(1<<j)-1<=n)
      {
        ana[i][j]=ana[i][j-1]&ana[i+(1<<j-1)][j-1];
        ord[i][j]=ord[i][j-1]|ord[i+(1<<j-1)][j-1];
      }
    long long cnt=0;
    for(int i=1;i<=n;i++)
     {
        int andx=q[i],orx=q[i];
        for(int j=i;j<=n;j++)
        {
            int l=j,r=n+1;//起点终点 
            int flag=1;
            andx=get_and(i,j);
            orx=get_or(i,j);
            if(a<=andx&&b>=andx&&c<=orx&&d>=orx) flag=0;
            //if(flag) continue;
            int ans=0;
            while(l<=r)
            {
                int mid=(l+r)/2;
                if(andx&&get_and(i,mid)==andx&&orx&&get_or(i,mid)==orx) l=mid+1,ans=mid;
                else r=mid-1;
            }
            if(ans)
            {
                if(a<=andx&&b>=andx&&c<=orx&&d>=orx) cnt+=(ans-j+1)%mod;
                j=ans;
            }
            else break;
        }
     }
     printf("%lld\n",cnt%mod);
}

t3
树形dp。。。,不会贴代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
LL mod = 1e9+7;
int n,k;
int a[1005];
int H[1005],X[2005],P[2005],tot;
inline void add(int x,int y){
    P[++tot]=y;X[tot]=H[x];H[x]=tot;
}
LL pw2[1005];
LL dp[1005][1005];

int dfs(int x,int fa){
    int siz=1;
    for(int i=H[x];i;i=X[i]){
        if(fa == P[i]) continue;
        for(int j=0;j<=n-a[P[i]];j++){
            dp[P[i]][j+a[P[i]]] = dp[x][j];
        }
        int tmp = dfs(P[i],x);
        for(int j=0;j<=n;j++){
            dp[x][j] = (pw2[tmp-1] * dp[x][j] % mod + dp[P[i]][j])% mod;
        }
        siz+=tmp;
    }
    return siz;
}
int main(){
    freopen("fruit.in","r",stdin);
    freopen("fruit.out","w",stdout);
    scanf("%d%d",&n,&k);

    pw2[0]= 1;
    for(int i=1;i<=n;i++) pw2[i] = pw2[i-1] * 2 % mod;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1,x,y;i<n;i++){
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    dp[1][a[1]] = 1;
    dfs(1,0);

    printf("%d\n",(int)dp[1][k]);



    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值