A - Doors and Keys
模拟即可
B - Anti-Fibonacci Permutation
题意:构造n个非斐波那契数列,即一个n的排列,对任意a[i],a[i+1],a[i+2],a[i]+a[i+1]!=a[i+2]。
解:递减的数列显然符合要求。考虑构造n-x,n-x-1,...1,n,n-1,...n-x+1,n=3时不成立,特判即可。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define maxn 1005 #define maxm 200005 #define eps 0.00000001 #define inf 0x7fffffff #define mod 1000000007 //#define int long long int n,k; signed main() { int T; scanf("%d",&T); while(T--){ scanf("%d",&n); if(n==3){ printf("3 2 1\n"); printf("1 3 2\n"); printf("3 1 2\n"); continue; } for(int i=n;i>=1;i--){ for(int j=i;j>=1;j--) printf("%d ",j); for(int j=n;j>=i+1;j--) printf("%d ",j); printf("\n"); } } return 0; } //n-x,n-x-1,...1,n,n-1,...n-x+1 //n!=3
C - Increase Subarray Sums
题意:令f(x)为给数列a中任意x个数加k后最大子数组的和,求f(0),f(1),...,f(n)的值。
解:首先排除n3的算法。dp了一下失败了,其实也能做,设dp[i][j][0/1]为到第i个,用了j个k,当前加不加k的答案。
考虑f(x)和什么有关。首先它要加k个数在不同的位置,那最好全加在子数组里面。令len[i]为长度为i的子数组元素和最大值。
f(k)=max(len[i]...len[n])+k*x
好了可以写了。注意继承之前的最大值,因为不是多出一个数和就会变大的。
D. Cross Coloring
题意:一开始有一个空白的n*m表格,每次选一个格子,将其行或列染成k种颜色中的随机一种,求最后表格有几种染色情况。
解:染色问题肯定从后往前看。对于某一行或某一列,只有一种染色情况。不同行和列染色之间互不干扰,多染一次色,就多k种不同的情况。也就是说,选的格子所在行或列没有被选过,则乘k。注意所有行或所有列都被涂过色后整张表格显然已经满了,任何之前的染色操作都被覆盖,但此时记录行和列的set仍不完全,应立即退出循环。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define maxn 1005 #define maxm 200005 #define eps 0.00000001 #define inf 0x7fffffff #define mod 998244353 //#define int long long int n,m,k,q; int ql[maxx],qr[maxx]; signed main() { int T; scanf("%d",&T); while(T--){ scanf("%d%d%d%d",&n,&m,&k,&q); for(int i=1;i<=q;i++) scanf("%d%d",&ql[i],&qr[i]); set<int> l,r; ll ans=1; for(int i=q;i>=1;i--){ if(l.size()==n||r.size()==m) break; int flag=0; if(!l.count(ql[i])) l.insert(ql[i]),flag=1; if(!r.count(qr[i])) r.insert(qr[i]),flag=1; if(flag) ans=(ans*k)%mod; } printf("%lld\n",ans); } return 0; }