题意:
有m个人,n场比赛。
第 i i i场比赛你获得 a i a_i ai名,总分为 b i b_i bi,选手分数为 1 1 1~ b i b_i bi。
名次为分数严格大于你的人数+1.
最后排名不超过 k k k的人拿到冠军.
问最后你是否一定能拿冠军。
题解:
最极端的情况,每次比赛都是0分。有 a i − 1 a_i-1 ai−1个人拿满分。那这 a i − 1 a_i-1 ai−1个人的排名一定都在你之上。
最后比较排名在你之上的人数有没有 k k k人。
还有 k = m k=m k=m时,一定可以拿冠军。
代码:
#include
using namespace std;
typedef __int128 i128;
typedef long long ll;
typedef double db;
const db PI = acos(-1);
typedef array<ll, 2> PII; // vector a(n + 1);
const ll inf = 2e18 + 10;
const int mod = 998244353;
const int maxn = 2e5 + 10;
bool multi = 1;
void Solve() {
ll n, m, k; cin >> n >> m >> k;
vector<ll> a(n + 1), b(n + 1);
ll summ = 0;
for(ll i = 1; i <= n; i ++ ) {
cin >> a[i];
summ += a[i] - 1;
}
for(ll i = 1; i <= n; i ++ ) {
cin >> b[i];
}
if(k == m || summ < k) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}
signed main() {
// freopen("test.in","r",stdin);
// freopen("code.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
ll T = 1;
if(multi) cin >> T;
while(T -- ) {
Solve();
}
return 0;
}
题意:
有n个成环的竹笋。
Alice 和 Bob 轮流执行如下,选择 [ 1 , k ] [1,k] [1,k]个连续竹笋拿走。Alice优先。
无法操作者输。
两人都绝顶聪明,问谁最后会赢。
题解:
情况1: n = k n=k n=k
Alice第一次操作直接全部拿走,必胜。
情况2: k = 1 k=1 k=1
每次拿一个,最后就是看n的奇偶性。
其余情况:
无论Alice拿多少个,Bob都可以取中间的1或2,分为两个一样长的连续段,无论Alice怎么操作,Bob都可以进行对称操作,那最后一步一定是Bob操作。Bob必胜。
代码:
#include
#define int long long
#define PII pair
using namespace std;
const int N =2e6+6;
int a[N];
void solve()
{
int n,k;
cin>>n>>k;
if(n==k){
cout<<'A';
return ;
}
if(k==1){
if(n%2){
cout<<'A';
}else cout<<'B';
return ;
}
cout<<'B';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
题意:
有n处地点要拍摄,一天有m段时间。
每处地点要在 l i l_i li~ R i R_i Ri的时间段拍摄,拍摄时间为连续的 t i t_i ti个时间段。
同一时间只能拍摄一处地方。问是否可以拍摄完这n处地方。
保证 l i + 1 < = l i , r i + 1 > = r i l_{i+1}<=l_i,r_{i+1}>=r_i li+1<=li,ri+1>=ri
题解:
画图,发现就是一层一层的,可以用dp思想解决。
假如前 i i i处拍摄在 x x x~ y y y时间段:
那第 i + 1 i+1 i+1处只可能在 x x x左边,或者 y y y右边。发现直线拍摄时间段都是相邻的,这样肯定是最优的选择。
d p [ i ] [ j ] = 0 / 1 dp[i][j]=0/1 dp[i][j]=0/1表示第 i i i层,以 j j j为x的时间段是否满足。
转移方程: d p [ i ] [ j ] = 1 dp[i][j]=1 dp[i][j]=1
在 x x x左边:
如果 j − t [ i + 1 ] > = l [ i + 1 ] j-t[i+1]>=l[i+1] j−t[i+1]>=l[i+1] -> d p [ i + 1 ] [ j − t [ i + 1 ] ] = 1 dp[i+1][j-t[i+1]]=1 dp[i+1][j−t[i+1]]=1
在 y y y右边:
如果: j + s u m [ i + 1 ] − 1 < = r [ i + 1 ] j+sum[i+1]-1<=r[i+1] j+sum[i+1]−1<=r[i+1] -> d p [ i + 1 ] [ j ] = 1 dp[i+1][j]=1 dp[i+1][j]=1
代码:
#include
#define int long long
#define PII pair
using namespace std;
const int N =5e3+6;
int dp[N][N];
int l[N],r[N],sum[N],t[N];
void solve()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>l[i]>>r[i]>>t[i];
sum[i]=sum[i-1]+t[i];
}
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
dp[i][j]=0;
}
}
for(int i=l[1];i+t[1]-1<=r[1];i++){
dp[1][i]=1;
}
for(int i=1;i<n;i++){
for(int j=1;j<=m;j++){
if(dp[i][j]){
if(j-t[i+1]>=l[i+1]){
dp[i+1][j-t[i+1]]=1;
}
if(j+sum[i+1]-1<=r[i+1]){
dp[i+1][j]=1;
}
}
}
}
int ok=0;
for(int i=1;i<=m;i++){
if(dp[n][i])ok=1;
}
if(ok){
cout<<"YES\n";
}else cout<<"NO\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
题意:
给定 a i , b i a_i,b_i ai,bi,构造出数组 c c c.
满足 ( a i x o r c i − 1 ) + ( b i x o r c i − 1 ) = c i (a_i xor c_{i-1})+(b_i xor c_{i-1})=c_i (aixorci−1)+(bixorci−1)=ci,特别 c 0 = c q c_0=c_q c0=cq
并且要求c数组为字典序最小。
题解:
a i a_i ai和 b i b_i bi最低位情况:
0 0 /1 1 最后无论异或多少,结果都是0
1 0 /0 1 最后无论异或多少,结果都是1
判断每一位的情况,就知道 c i c_i ci的值。
代码:
#include
using namespace std;
#define int unsigned int
#define rep(i,j,k) for (int i=(j);i<=(k);i++)
const int N=1000005;
int n,m,sn;
int a[N],b[N],c[N];
void work()
{
cin >> n;
rep(i,0,n-1) cin >> a[i] >> b[i];
rep(i,0,n-1) c[i]=(a[i]^b[i])&1;
rep(k,1,31)
{
rep(i,0,n-1)
{
int bas=c[(i+n-1)%n]&((1<<k)-1);
int d=(a[i]^bas)+(b[i]^bas);
c[i]^=d&(1u<<k);
}
}
rep(i,0,n-1) cout << c[i] << '\n';
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin >> T;
while (T--) work();
return 0;
}