题外话
其实这场我没打(太困了),咕咕咕了好久才写了四个题QAQ
A
A题意
问你是否通过题面上给的四个移动方式(全部使用完)使得从一开始的位置移动没有出界
A思路
其实就是判断上下,左右之间的差,和界限的距离, 注意要关注一下想x1 ==x2 和y1 ==y2 的这两种情况
A代码
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
ll c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return f*x;
}
const int N =100010;
int n , k, m ;
ll mod = 1e9+7;
ll ar[100010];
int h[N] , ne[2*N] , idx, e[2*N];
int dep[N], f[1010][1010];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >>n;
while (n--){
int a ,b,c,d;
cin >>a>>b>>c>>d;
int x,y,x1,y1,x2,y2;cin >>x>> y >>x1>>y1>>x2>>y2 ;
int u, l;u = a-b;l = c-d ;
if(x1 ==x2){
if(a==b&&b!=0){
cout<<"No"<<endl;
continue;
}
}
if(y1 ==y2){
if(c==d && c!=0){
cout<<"No"<<endl;
continue ;
}
}
if(u<0){
if(x-u>max(x1,x2)){
cout<<"NO"<<endl;
continue ;
}
}
else if(u>=0){
if(x-u<min(x1,x2)){
cout<<"NO"<<endl;
continue ;
}
}
if(l < 0){
if(y-l>max(y1,y2)){
cout<<"NO"<<endl;
continue ;
}
}
else if(l>=0){
if(y-l<min(y1,y2)){
cout<<"NO"<<endl;
continue ;
}
}
cout<<"YES"<<endl;
}
return 0;
}
B
B题意
给你一堆数, 让你通过GCD的性质(一组中的所有数,与其他数gcd都大于1的可以是一个颜色) ,分出需要多少颜色(不需要搞出最多和最少 )
B思路
先看数据范围哈哈!1000, 然后发现这个题和质因数有很大的关系,
- 因为数据范围是1000, 所以一共在1000里面有11个质数,且最大的是31
- 通过唯一分解定理, 可知道所有数都可以分为质因数
- 因为质因数一共就只有11个,符合题面上的最大m《=11 的条件, 所以只需要让每个数的最小质因数相同的为一组就行(最大啥的都可以)
B代码
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
ll c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return f*x;
}
const int N =100010;
int n , k =1, m ;
int ar[10010];
int cr[10010];
void clear(unsigned char *pta, int size )
{
while(size>0)
{
*pta++ = 0;
size --;
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >>n;
while(n--){
cin >>m;
k =1 ;pii br[1010];
for(int i =0 ;i<m;i++)cin >> ar[i];
for(int i=0;i<m;i++){
for(int j=2;j<=ar[i]/j;j++){
if(ar[i]%j==0){
// cout<<j<<endl;
if(br[j].first == 0){
cr[i] = k;
br[j].second = k;
// cout<<br[j].second << " "<<j <<endl;
k++;
}
else if(br[j].first >0)cr[i] = br[j].second;
br[j].first ++ ;
break;
}
}
}
int cnt =0 ;
for(int i=2;i<=31;i++){
if(br[i].first!=0)cnt ++ ;
}
cout<<cnt <<endl;
for(int i=0;i<m;i++)cout<<cr[i]<<" ";
cout<<endl;
}
return 0;
}
C
C题意
- S 自身是要回文的
- 每k组也是要回文
- m可以整除k
问你最少需要修改多少字符符合上述条件
C思路
- 直觉一想,肯定是每个有关系的字符中, 把剩余和最多字符不相同的字符修改成最多的那个字符
- 然后因为每k组要回文,所以先判断一下k的奇偶性质
- 然后通过画图, 其实你可以 得到这个关系$ i +jk == jk+k-i-1 $ 其中,j是k的第几组
- 剩下的就是通过相加和相减求出最少的修改次数即可
C代码
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
ll c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return f*x;
}
const int N =100010;
int n , k, m ;
ll mod = 1e9+7;
ll ar[100010];
int h[N] , ne[2*N] , idx, e[2*N];
int dep[N], f[1010][1010];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >>n;
while(n--) {
cin >>m>>k ;string s;
cin >>s;
ll sum =0;
for(int i=0;i<((k&1) ? (k+1)/2: k/2);i++){
int cnt=0;map<char , int > mp;
for(int j=0;j<m/k;j++){
if((k&1) && i ==(k+1>>1) -1)mp[s[i+j*k]]++;
else if(s[i+j*k] == s[j*k+k-i-1 ])mp[s[i+j*k]]+=2;
else mp[s[i+j*k]]++ ,mp[s[j*k+k-i - 1 ]]++;
cnt= max(mp[s[i+j*k]],max( mp[s[j*k+k-i-1]], cnt));
}//cout<<cnt[i]<<" "<< i << endl;
// cout<<cnt<<endl;
if(k&1){
if(i == (k+1)/2-1)sum +=m/k-cnt;
else sum +=2*m/k-cnt;
// cout<<sum<<endl;
}
else sum +=2*m/k-cnt;
}
cout<<sum<<endl;
}
return 0;
}
D
D题意
- 假设有一个数字矩阵,每次可以向下或向右,问从左上角走到右下角的数字和最多是多少,那么显然这是一个dp。
- 现在不问你数字和,而是把路径上的所有数都&起来,如果还是dp显然是错的。假设dp的到的结果是x,正确答案是y。
- 现在给定k,需要你构造一个矩阵,使得|y-x|=k
懒得自己写了(搬运)原题解传送门
D思路
还是上面的大佬的,这个大佬的想法真的很棒
D代码
还是上面大佬的思路下的代码,我就不献丑了