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;
}