1 条题解
-
0
自动搬运
来自洛谷,原作者为

duyi
大家好我是于之航爸爸搬运于
2025-08-24 22:14:15,当前版本为作者最后更新于2020-07-02 21:23:17,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
强烈推荐,戳此↓,看看我的博客
题目大意
给定两个整数, 和一个01串。我们设是一个二进制数,它的二进制表示,就是重复次。请你选出个不同的、小于的非负整数(也就是值在之间),使得它们的异或和为。
数据范围:。
本题题解
假设我们已经知道了(也就是把重复次大力展开),该怎么做?设选出的这个数为。为了保证这个数互不相同且都小于,不妨设。不妨设。
因为很小,考虑状压DP。设表示考虑了的前位(从高到低);是一个长度为的二进制数,对于第个位置 (),如果当前(只考虑数的前位),则第位为,否则第位为。转移时,枚举的第位分别填什么,这样可以计算出新的。令即可。
这个DP的时间复杂度是$O(|R|\cdot (2^n)^2\cdot n)=O(k\cdot |S|\cdot 2^{2n}\cdot n)$的,无法通过本题。
发现上面的这个DP,没有用到“是由一个非常短的串,重复次得来的”,这一特殊条件。我们发现,在的次重复中,每一次的转移其实都是一样的。那么就容易想到做矩阵快速幂。
那么关键就是要求出转移矩阵:表示从转移到的系数 ()。可以枚举,令,然后对做一遍上面的那个DP,就可以对所有求出了。这部分时间复杂度。可以承受。
然后就对这个大小为的矩阵做矩阵快速幂即可。这部分时间复杂度。
总时间复杂度。
参考代码:
//problem:LOJ2075 #include <bits/stdc++.h> using namespace std; #define pb push_back #define mk make_pair #define lob lower_bound #define upb upper_bound #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef unsigned int uint; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; const int MOD=1e9+7; inline int mod1(int x){return x<MOD?x:x-MOD;} inline int mod2(int x){return x<0?x+MOD:x;} inline void add(int& x,int y){x=mod1(x+y);} inline void sub(int& x,int y){x=mod2(x-y);} inline int pow_mod(int x,int i){int y=1;while(i){if(i&1)y=(ll)y*x%MOD;x=(ll)x*x%MOD;i>>=1;}return y;} const int MAXN=7,MAXK=1e5,MAXS=50; const int SIZE2=1<<MAXN; int n,K,len,bitcnt[SIZE2],dp[MAXS+5][SIZE2]; char s[MAXS+5]; struct Matrix{ int a[SIZE2][SIZE2],sz; Matrix(){ memset(a,0,sizeof(a)); sz=0; } }; Matrix operator*(const Matrix& X,const Matrix& Y){ Matrix Z; assert(X.sz==Y.sz); Z.sz=X.sz; for(int i=0;i<=X.sz;++i){ for(int j=0;j<=X.sz;++j){ for(int k=0;k<=X.sz;++k){ add(Z.a[i][j],(ll)X.a[i][k]*Y.a[k][j]%MOD); } } } return Z; } Matrix mat_pow(Matrix X,int i){ Matrix Y; Y.sz=X.sz; for(int j=0;j<=X.sz;++j)Y.a[j][j]=1; while(i){ if(i&1)Y=Y*X; X=X*X; i>>=1; } return Y; } int main() { cin>>n>>K; cin>>(s+1);len=strlen(s+1); int sz=(1<<n)-1; for(int i=1;i<=sz;++i)bitcnt[i]=bitcnt[i>>1]+(i&1); Matrix trans; trans.sz=sz; for(int st=0;st<=sz;++st){ memset(dp,0,sizeof(dp)); dp[0][st]=1; for(int i=1;i<=len;++i){ for(int j=0;j<=sz;++j)if(dp[i-1][j]){ for(int k=0;k<=sz;++k)if(bitcnt[k]%2==0){ static int curs[MAXN+5]; curs[0]=s[i]-'0'; for(int l=1;l<=n;++l)curs[l]=((k>>(l-1))&1); bool fail=false; int newj=0; for(int l=1;l<=n;++l){ if((j>>(l-1))&1){ //之前是等于的 if(curs[l]>curs[l-1]){fail=1;break;} if(curs[l]==curs[l-1])newj|=(1<<(l-1)); } } if(fail)continue; add(dp[i][newj],dp[i-1][j]); } } } for(int ed=0;ed<=sz;++ed){ trans.a[st][ed]=dp[len][ed]; } } trans=mat_pow(trans,K); Matrix res; res.a[0][sz]=1; res.sz=sz; res=res*trans; cout<<res.a[0][0]<<endl; return 0; }
- 1
信息
- ID
- 4780
- 时间
- 1000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者