待补:
设答案 为 dp[n];
考虑第n个人的面具
1.与第一个相同,这时候相当于n-1个人,即dp[n-1]
2. 与第一个不同,根据同或不等于0的原则最后一个有 (2^k-2)中选择(排除自身和同或等于0)
这个时候直接打表就足够了,但是化简一下算个快速幂就出来了
g(2)=2k∗(2k−1) g ( 2 ) = 2 k ∗ ( 2 k − 1 )
g(1)=2k; g ( 1 ) = 2 k ;
g(0)=1 g ( 0 ) = 1
#include
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
int n,m;
ll qpow(ll a,ll b){ll s=1;while(b>0){if(b&1)s=s*a%mod;a=a*a%mod;b>>=1;}return s;}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll ans;
cin>>n>>m;
ll k=(qpow(2,m)-1)%mod;
if(n%2==0)
ans=((qpow(k,n)+k))%mod;
else
ans=((qpow(k,n)+1))%mod;
printf("%lld\n",ans);
}
return 0;
}
记忆化搜索
const int maxn = 1e5+100;
int a[maxn],b[maxn],c[maxn],cnt[maxn];
int result[maxn][300];
int n,m,l,r;
int check(int n){
if(n <-100) return -100;
if(n > 100) return 100;
return n;
}
int dfs(int pos,int m){
if(pos == n){
if(m <= l)
return 1;
else if(m >= r)
return 0;
else
return 2;
}
int t = pos&1;
int aa,bb,cc;
aa=bb=cc=-1;
if(a[pos]){
int x = pos+1,y = check(m+a[pos]);
if(result[x][y+100] != 1000)
aa = result[x][y+100];
else
aa = result[x][y+100] = dfs(x,y);
if(aa==t) return t;
}
if(b[pos]){
int x = pos+1,y = check(m-b[pos]);
if(result[x][y+100] != 1000)
bb = result[x][y+100];
else
bb = result[x][y+100] = dfs(x,y);
if(bb==t) return t;
}
if(c[pos]){
int x = pos+1,y = -m;
if(result[x][y+100] != 1000)
cc = result[x][y+100];
else
cc = result[x][y+100] = dfs(x,y);
if(cc==t) return t;
}
if(aa == 2||bb == 2||cc == 2) return 2;
return !t;
}
int main(void)
{
cin>>n>>m>>r>>l;
rep(i,0,n+1)
rep(j,-100,100+1)
result[i][j+100] = 1000;
rep(i,0,n) scanf("%d%d%d",&a[i],&b[i],&c[i]);
int ans = dfs(0,m);
if(ans == 0) printf("Good Ending\n");
else if(ans == 1) printf("Bad Ending\n");
else puts("Normal Ending");
return 0;
用线段树维护前缀和,每一次单点更改x点的值,相当于更新所有x-n的前缀和,查询的时候,是l,r的前缀和的和- (r-l+1)*sum(l-1)
#include
#define rep(i,a,n) for (int i=a;i
using namespace std;
typedef long long LL;
const LL mod = 1e9 + 7;
#define lson (o<<1)
#define rson (o<<1|1)
LL qpow(LL a,LL b){LL s=1;while(b>0){if(b&1)s=s*a%mod;a=a*a%mod;b>>=1;}return s;}
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
int dr[2][4] = {1,-1,0,0,0,0,-1,1};
typedef pair<int,int> P;
const int maxn = 1e6+10;
int ar[maxn];
const int maxnode = 4*maxn;
LL sumv[maxnode];
LL addv[maxnode];
LL S[maxn];
void Fre(){
freopen("input.txt","r",stdin);
freopen("output.txt","w+",stdout);
}
void build(int o,int L,int R)
{
int m = (R+L)>>1;
if(L == R) sumv[o] = S[L];
else
{
build(lson,L,m);
build(rson,m+1,R);
sumv[o] = sumv[lson]+sumv[rson];
}
}
void update(int o,int L,int R,int y1,int y2,int add){
// cout<<1<
if(y1 <= L && y2 >= R){
addv[o] += add;
}
else{
// assert(L,)
sumv[o] += 1ll*(min(R,y2)-max(L,y1)+1)*add;
int M = (R+L)>>1;
if(y1 <= M) update(lson,L,M,y1,y2,add);
if(y2 > M) update(rson,M+1,R,y1,y2,add);
}
}
LL query(int o,int L,int R,int y1,int y2){
LL _sum = 0;
if(y1 <= L&&y2 >= R){
_sum += sumv[o] +addv[o]*(R-L+1);
}
else{
int M = (R+L)>>1;
sumv[o] = sumv[o]+1ll*(R-L+1)*addv[o];
addv[lson] += addv[o];
addv[rson] += addv[o];
addv[o] = 0;
if(y1 <= M) _sum += query(lson,L,M,y1,y2);
if(y2 > M) _sum += query(rson,M+1,R,y1,y2);
}
return _sum;
}
int main(void)
{
int n,q;
cin>>n>>q;
rep(i,1,n+1) {
scanf("%d",&ar[i]);
S[i] = S[i-1]+ar[i];
}
build(1,1,n);
rep(i,0,q){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
LL ans = 0;
if(op==1) {
ans = query(1,1,n,x,y);
if(x!=1)
ans -= 1ll*(y-x+1)*query(1,1,n,x-1,x-1);
printf("%lld\n",ans);
}
else {
update(1,1,n,x,n,y-ar[x]);
ar[x] = y;
}
}
return 0;
}
具体题解参考CatDsy
可以用bitset 优化矩阵的乘法
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
int dr[2][4] = {1,-1,0,0,0,0,-1,1};
typedef pair<int,int> P;
const int maxn = 70;
struct Matrix{
int n,m;
int a[maxn][maxn];
Matrix(int nn = 0,int mm = 0):n(nn),m(mm){me(a);}
};
Matrix operator *(const Matrix &a,const Matrix &b){
Matrix c(a.n,b.m);
bitset<70> A[70],B[70];
rep(i,0,a.n)
rep(j,0,a.m)
A[i][j] = a.a[i][j];
rep(i,0,b.n)
rep(j,0,b.m)
B[j][i] = b.a[i][j];
for(int i = 0;i < a.n; ++i){
for(int j = 0;j < b.m; ++j){
c.a[i][j] = (A[i]&B[j]).count()&1 ;
}
}
return c;
}
int A[10][10],B[10][10];
void solve(int n,int m,int t){
m /= 2;
Matrix a(1,n*n),M(n*n,n*n);
rep(i,0,n){
rep(j,0,n){
a.a[0][i*n+j] = A[i][j]&1;
for(int p = i-m; p <= i+m; ++p){
for(int q = j-m; q <= j+m; ++q){
if(p < 0||p >= n||q < 0||q >= n) continue;
M.a[p*n+q][i*n+j] = B[p-i+m][q-j+m]&1;
}
}
}
}
// DEBUG;
while(t > 0){
if(t & 1)
a = a*M;
M = M*M;
t >>= 1;
// DEBUG;
}
int cnt = 0;
rep(i,0,n)
rep(j,0,n)
if(a.a[0][i*n+j])
cnt++;
printf("%d\n",cnt);
}
int main(void){
int T;
scanf("%d",&T);
while(T--){
int N,M,t;
scanf("%d%d%d",&N,&M,&t);
rep(i,0,N)
rep(j,0,N)
scanf("%d",&A[i][j]);
rep(i,0,M)
rep(j,0,M)
scanf("%d",&B[i][j]);
solve(N,M,t);
}
return 0;
}