SNCPC2024 vp
按照自认为的难度顺序排序
F题.P10696 [SNCPC2024] 写都写了,交一发吧
找最大值
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
long long mx=0;
long long cm=0;
for(int i =1;i<=n;i++){
long long temp;
cin>>temp;
if(temp>=mx){
cm=mx;
mx=temp;
}
}
long long ans=mx&mx;
cout<<ans<<endl;
}
return 0;
}
P10691 [SNCPC2024] chmod模拟题
输入三个三位数 每一位的二进制前三位的0或者1决定输出的结果
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
string temp;
cin>>temp;
int s[3];
s[0]=(int)temp[0]-48;
s[1]=(int)temp[1]-48;
s[2]=(int)temp[2]-48;
char ans[9];
if(s[0]%2&&1){
ans[2]='x';
s[0]/=2;
}
else {
ans[2]='-';
s[0]/=2;
}
// cout<<s[0]<<endl;
if(s[0]%2&&1){
ans[1]='w';
s[0]/=2;;
}
else {
ans[1]='-';
s[0]/=2;
}
// cout<<s[0]<<endl;
if(s[0]&&1){
ans[0]='r';
s[0]/=2;
}
else {
ans[0]='-';
s[0]/=2;
}
// cout<<s[0]<<endl;
if(s[1]%2&&1){
ans[5]='x';
s[1]/=2;
}
else {
ans[5]='-';
s[1]/=2;
}
if(s[1]%2&&1){
ans[4]='w';
s[1]/=2;
}
else {
ans[4]='-';
s[1]/=2;
}
if(s[1]%2&&1){
ans[3]='r';
s[1]/=2;
}
else {
ans[3]='-';
s[1]/=2;
}
//
if(s[2]%2&&1){
ans[8]='x';
s[2]/=2;
}
else {
ans[8]='-';
s[2]/=2;
}
if(s[2]%2&&1){
ans[7]='w';
s[2]/=2;
}
else {
ans[7]='-';
s[2]/=2;
}
if(s[2]%2&&1){
ans[6]='r';
s[2]/=2;
}
else {
ans[6]='-';
s[2]/=2;
}
for(int i = 0;i<=8;i++){
cout<<ans[i];
}
cout<<endl;
}
return 0;
}
丑陋的暴力 可以写一个循环
B题 P10692 [SNCPC2024] 表达式矩阵
模拟+打表+贪心
首先外层为1 内部全部填入*
当一行或者一列为11*11的情况将*改为+
一行或者一列最多只能放一个+
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
char mp[n+5][m+5];
memset(mp,'1',sizeof(mp));
if((m-2)%2==0||(n-2)%2==0){
for(int i = 2;i<=n-1;i+=2){
if(m%2==1||n%2==1){
for(int j = 2;j<=m-1;j+=2){
mp[i][j]='*';
if(i+1<=n-1&&j+1<=m-1)mp[i+1][j+1]='+';
if(n>6||m>6){
if(i+1<=n-3&&j+1<=m-1&&n>=m){
mp[i+1][j+1]='*';
if(m==5&&i+1<=n-3&&j+1<=m-1&&n>=m) mp[i+1][j+1]='+';
}
else if(i+1<=n-1&&j+1<=m-3&&m>n){
mp[i+1][j+1]='*';
if(n==5&&i+1<=n-1&&j+1<=m-3&&m>n)mp[i+1][j+1]='+';
}
}
}
}
else{
for(int j = 2;j<=m-1;j+=2){
mp[i][j]='*';
if(i+1<=n-1&&j+1<=m-1)mp[i+1][j+1]='*';
}
}
}
}
else {
for(int i = 2;i<=n-1;i+=2){
for(int j = 2;j<=m-1;j+=2){
mp[i][j]='*';
if(i+1<=n-1&&j+1<=m-1)mp[i+1][j+1]='+';
if(n>=6||m>=6){
if(n!=m){
if(i+1<=n-3&&j+1<=m-1&&n>=m){
mp[i+1][j+1]='*';
if(m==5&&i+1<=n-3&&j+1<=m-1&&n>=m) mp[i+1][j+1]='+';
}
else if(i+1<=n-1&&j+1<=m-3&&m>n)mp[i+1][j+1]='*';
if(n==5&&i+1<=n-1&&j+1<=m-3&&m>n)mp[i+1][j+1]='+';
}
else{
if(i+1<=n-3&&j+1<=m-3){
mp[i+1][j+1]='*';
}
mp[n-2][m-2]='*';
}
}
}
}
}
if(n==8&&m==7){
mp[3][3]='+';
mp[5][5]='+';
mp[7][3]='*';
}
if(n==7&&m==8){
mp[3][3]='+';
mp[3][7]='*';
mp[5][5]='+';
}
if(n==9&&m==7){
mp[7][5]='*';
mp[5][5]='+';
mp[3][3]='+';
}
if(n==7&&m==9){
mp[5][5]='+';
mp[5][7]='*';
mp[3][3]='+';
}
if(n==9&&m==8){
mp[3][3]='+';
mp[7][3]='*';
mp[7][5]='*';
mp[5][5]='+';
}
if(n==8&&m==9){
mp[3][3]='+';
mp[3][7]='*';
mp[5][7]='*';
mp[5][5]='+';
}
if(n==9&&m==9){
mp[7][3]='*';
mp[3][3]='+';
mp[3][7]='*';
mp[5][5]='+';
mp[5][7]='*';
mp[7][7]='+';
mp[7][5]='*';
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
cout<<mp[i][j];
}
cout<<endl;
}
return 0;
}
M题P10703 [SNCPC2024] 窗花
思维题
很显然 比如放一个点在(2,2)如果另一个点在他的上下左右即距离为1
他们重叠的面积为0.5 其他位置不重叠 只需一个个遍历 判断上下左右是否重叠将面积累加即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
bool vis[101][101];
double ans;
main(){
cin>>n;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
if(vis[x][y]){
continue;
}vis[x][y]=true;
ans+=2;
if(vis[x-1][y])ans-=0.5;
if(vis[x+1][y])ans-=0.5;
if(vis[x][y-1])ans-=0.5;
if(vis[x][y+1])ans-=0.5;
}cout<<ans;
return 0;
}
题目说xy的范围为1到99,所以不会越界不用判断边界
G题P10697 [SNCPC2024] 消失的数字
给定n和x问从1到n中不包含x的数有多少,讨论当x等于9的时候包含的数为9进制的n个
当x不为9的时候 不妨当x为9 遍历每一位 当该位大于x 将他减少1;
代码如下
#include<bits/stdc++.h>
#define int long long
using namespace std;
bool vis[101][101];
double ans;
main(){
int t;
cin>>t;
while(t--){
long long n,x;
cin>>n>>x;
long long ans=0;
int t=1;
if(x==9){
while(n>0){
if(n%10==9){
ans+=t*8;
}
else ans+=t*(n%10);
n/=10;
t*=9;
}
}
else{
while(n>0){
if(n%10==x){
ans+=t*8;
}
else if(n%10>x){
ans+=t*(n%10-1);
}
else ans+=t*(n%10);
n/=10;
t*=9;
}
}
cout<<ans+1<<endl;
}
return 0;
}
C题P10693 [SNCPC2024] 换座位
给一个数组a[n]; ai可以取到2n,对于1-n每个i本来的位置是i想坐的位置是ai
求最大有多少能坐到自己想坐的位置
我们将i和ai连线
可以得到以下情况
1.连成一个带环的线(或者环)
例如1->2->3->2这种情况1只能在他本身的位置 2,3能坐到自己喜欢的位置成为一个环
2.连成树
例如 1->2->3->6
4->5->6;
形成一颗以6为顶点的树,这种情况显然求该顶点的最长边
实现思路,用拓扑排序求出环的长度 得到ans
然后求n+1到2*n(因为当i<=n时 他们才有喜欢的座位,所以顶点一定是>n的)
枚举这些点的最长边加到ans里面 得到答案
#include<bits/stdc++.h>
using namespace std;
const int N = 2*10e5;
vector<int> G[N];
vector<int> C[N];
int r[N];
int a[N];
bool h[N];
long long ans=0;
int n;
void tp(int n){
int st=1;
while(st>0){
st--;
for(int i = 1;i<=n;i++){
if(r[i]==0){
r[i]--;
st=1;
r[G[i][0]]--;
}
}
}
for(int i = 1;i<=n;i++){
if(r[i]==1){
h[i]=true;
ans++;
}
}
}
int mx;
int dp;
void dfs(int x){
mx=max(dp,mx);
if(C[x].size()>0){
for(int i = 0;i<C[x].size();i++){
dp++;
dfs(C[x][i]);
dp--;
}
}
else return;
}
int main(){
cin>>n;
for(int i = 1;i<=n;i++){
cin>>a[i];
G[i].push_back(a[i]);
C[a[i]].push_back(i);
r[a[i]]++;
}
tp(n);
for(int i = n+1;i<=2*n;i++){
dp=0;
mx=0;
dfs(i);
ans+=mx;
}
cout<<ans<<endl;
return 0;
}
博弈+数学 lnc和ljj拿棋子
lnc是先手 一共有x个棋子,lnc选一个进制k,每次只能拿lnc数先拿完的赢
问最小的进制k是多少 lnc数为所有k禁止下所有数位的乘积为自身因子的数
例如
当 k=10k=10 时,y=(36)10y=(36)10 是 LNC 数,因为 (3×6)∣36
当 k=4k=4 时,y=(12)4 y=(12)4 是 LNC 数,因为转换成十进制后 (12)4=(6)10(12)4=(6)10,而 (1×2)∣6
不妨设一个数字为32
他的二进制是100000
当lnc先手时 他的因数不能为0 所以他每一位都有数字
因为x末尾为0,不管他取多少的lnc数,棋子的末尾总会不为0,
此时对手取lnc数肯定会使得末尾为0,最后对手胜
因此 当取k进制 x末尾不为0时 lnc可以取一个数使得末尾为0 以此类推 他能获胜
只需枚举k判断x是否为k的倍数即可;
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t; cin >> t;
while(t--){
int n; cin >> n;
for(int x=2;;x++){
if(n % x){
cout << x << '\n';
break;
}
}
}
return 0;
}