9.17 考试
(首先喷一下出题人 这题真优(du)美(liu))
t1
题意 :
n*m矩阵 每个数 , 给你两个操作, 可以执行任意多次
<1> 对某一行 ,所有数字加1;
<2> 对某一列 , 所有数字加1;
如果执行完上述操作之后,矩阵中某个数变成了3,6,9,12其中的某一个,我们认为这个数是稳的。
给定初始矩阵,求出任意执行操作之后稳数的最多个数
思路:
首先想到爆搜 emmm, 然额 不知道搜啥
摆性质: 存在一种最优方案,使得在每一行每一列加上的数都不超过2
证明 : 假设一个操作使某一行或某一列加上了x且x大于2,则如果让x减去3,则x仍然是非负整数,这一行(列)内3的倍数的个数没有变,并且小于等于12的数的个数会不变或更多。这样我们就证明了当x≥3时某一行(列)加上不会比加上x更劣。
蓝后就有思路了;
先枚举每一行 加多少, 再枚举计算每一列加多少, 最后按列统计答案 ;
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#define N 1000005
#define inf 1e9
#define LL long long
#define qwq cout<<"!!!!!"<<endl;
using namespace std;
int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f*x;
}
int xx, yy, ans=-23333,n, m, a[20][20], md[20];
int zz[20][3];//第 i 列有多少个% 3 ==k
int check(int x)
{
return (x%3==0&&x<=12);
}
void dfs(int cnt)
{
if(cnt==n + 1) {
int res = 0;
for (int j = 1; j <= m; j++) {
zz[j][0]=zz[j][1]=zz[j][2]=0;
for(int i = 1; i <= n; i ++)
for(int k = 0; k <= 2; k ++)
zz[j][k] += check(a[i][j] + md[i] + k);
res += max(max(zz[j][0],zz[j][1]), zz[j][2]);
}
ans = max(res, ans);
return ;
}
for(int i = 0; i <= 2; i++)
md[cnt] = i, dfs(cnt + 1);
}
signed main()
{
freopen("zzx.in","r",stdin);
freopen("zzx.out","w",stdout);
n = read();
m = read();
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
a[i][j] = read();
dfs(1);
printf("%d ",ans);
return 0;
}
T2.
题面:
【题目描述】
给定一个长度为偶数的排列p,你每次可以选取p排列中相邻的两个元素,假如分别是x和y,那么把x和y加入一个序列q的末尾,并将x和y从排列p中删除。重复上述过程,直到p中没有元素,显然最终q序列也是一个排列。例如$p=(1,3,2,4)$,第一次可以选取3,2这两个元素加入q,并且从p中删除,此时$p=(1,4)$,第二次可以选取1,4这两个元素加入q,此时p为空,$q=(3,2,1,4)$。观察上述过程,最终q序列可能会有很多方案,请你输出所有可能方案中,q的字典序最大的。
字典序的比较方式如下,假设有两个长度同为n的序列a,b。我们找到最大的t,使得。之后比较与,如果,我们就认为a的字典序比b小,反之亦然。
【输入格式】
第一行包含一个正整数 n。第二行 n 个数,表示排列 p。
【输出格式】
一行 n 个数,表示字典序最大的序列 q。
【输入样例1】
4
3 1 4 2
【输出样例1】
4 2 3 1
【输入样例2】
6
6 5 4 1 3 2
【输出样例2】
6 5 4 1 3 2
【数据规模及约定】
对于20%的数据,n≤10。
对于60%的数据,n≤1,000。
对于100%的数据,n≤100,000。
思路:
貌似看上去很简单,然而发现并不是这样%%Theaker
就是每次找一个最大值 x 和一个次大值 y
如果x是当前最后一个元素, 就把y和y的下一个元素取出;
否则 把y和y的下一个元素取出
重点是咋维护呢?(链表连起来)
然后你就会有体会到 数组套数组 套了三四层(真kongbu, 感觉度数会长100度。。。)
像这样
a[a[a[ a[t.id].nxt].nxt]].val
然后就出现了指针选手(指针大发真的吼)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include <queue>
#define N 100005
#define inf 1e9
#define LL long long
#define qwq cout<<"!!!!!"<<endl;
using namespace std;
const int N = 100010;
inline int read()
{
int x = 0 , f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
struct node
{
int val , vis;
node *nxt , *fa;
node () {val = vis = 0;nxt = fa = NULL;}
}*root;
struct num
{
int val;
node *p;
friend bool operator < (const num & a,const num & b) { return a.val < b.val;}
};
int n , cnt;
priority_queue<num>q;
int main()
{
freopen("ysy.in","r",stdin);
freopen("ysy.out","w",stdout);
n = read();
node *p = root = new node();
for(int i = 1;i <= n;i ++)
{
p -> val = read();
q.push((num){p -> val,p});
if(i < n)
{
p -> nxt = new node();
p -> nxt -> fa = p;
p = p -> nxt;
}
}
while(cnt != (n >> 1))
{
node *p = q.top().p;
q.pop();
if(p -> nxt == NULL) continue;
if(p -> vis || p -> nxt -> vis) continue;
printf("%d %d ",p -> val,p -> nxt -> val);
cnt ++;
if(p -> fa && p -> nxt && p -> nxt -> nxt)
{
p -> nxt -> nxt -> fa = p -> fa;
p -> fa -> nxt = p -> nxt -> nxt;
}
p -> vis = 1;
p -> nxt -> vis = 1;
}
fclose(stdin);
fclose(stdout);
return 0;
}
毒瘤T3
题意:
没有什么能够阻挡,你对被阿的向往。天天AK的生涯,你的心了无牵挂。
虐过大佬的比赛,也曾装弱装逼。当你低头的瞬间,才发现旁边的人。
把你的四肢抬起来,使劲地往门上撞。盛开着永不凋零,黑莲花。
——《黑莲花》
给你一个数列, 两个操作 :
1 l r x:表示区间加上x。
2 l r p:询问
的值。
思路:
( 机房巨佬全用的树状数组, 就本蒟蒻在傻傻的分块 )
1、对于第一个操作, 显然乱七八糟的数据结构的是随便套的 ;
2、这就贼恶心了,
显然要暴力搞
话说考场上, 半个小时的时间, 一直在, (真是傻到家了)
蓝后就想起来这不是 嘛, 不会是 吧(没错就是它)
改一下, 震惊! 过样例了。。。再套上扩展欧拉定理, 对就这样(然后就过了两个点)
正解思路:
首先这是一道数据结构+数论的好(duliu)题。
而对于询问区间(其询问结果记作),有:
(假设上式中出现的模p意义下的幂指数都大于等于)
然后你会发现
(然而我在考试时推到上一步了 ,并没有发现发现啥)
(啊。还是我太弱了)
将 p 不断变 只需, 次就变成 1 , 指数为1, 就可以直接算;
所以对于递归
1、 直接返回 ;
2、否则递归到,记其为, 如果则返回 , 否则返回
。
然后就有一个新的问题 : 递归怎么判断指数大小.......由于 ,
所以,我们只需要取出的前5个数(如果的区间长度不足5则取区间内所有数,如果内第一个1出现的位置为x则取内所有数)
如果取出的数的个数为5则一定大于。否则可以大力快速幂判断指数是否大于等于。
可以用线性的欧拉筛预处理欧拉函数。
虽然出题人把时间开到9s, 但我并不觉得他很liangxin
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#define N 500005
#define int long long
#define LL long long
#define qwq cout<<"!!!!!"<<endl;
const int maxx = 2e7+5;
using namespace std;
int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f*x;
}
int n, m, a[N];
int len, pos[N], ll[N], rr[N], num, add[N];
int opt, xx, yy, zz, flag;
int phi[maxx], vis[maxx], prime[maxx], cnt;
void yych()
{
len = sqrt(n);
num = n/len; if(n%len != 0)num++;
for(int i = 1; i <= n; i++)
pos[i] = (i-1)/len +1;
for(int i = 1; i <= num; i++) {
ll[i] = (i-1)*len +1;
rr[i] = i*len;
}rr[num] = n;
}
void chenge(int l, int r, int x)
{
if(pos[l]==pos[r])
{
for(int i = l; i <= r; i ++)
a[i] +=x;
return;
}
for(int i = l; i <= rr[pos[l]]; i++)
a[i] += x;
for(int i = pos[l]+1; i <= pos[r]-1; i++)
add[i] += x;
for(int i = ll[pos[r]]; i <= r; i++)
a[i] += x;
}
int power(int x, int y, int p)
{
int ans = 1;
if(x >= p) flag = 1, x %= p;
while(y)
{
if(y&1) ans = ans * x;
x = x * x;
if(x >= p) flag = 1, x %= p;
y >>= 1;
if(ans >= p) flag = 1, ans %= p;
}
return ans;
}
void zh_dou()
{
phi[1]=1;
for(int i=2;i<=20000008;i++)
{
if(!vis[i])
{
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&prime[j]*i<=20000008;j++)
{
vis[prime[j]*i]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
int ask(int l, int r, int p)
{
if(l == r|| p == 1)
return (a[l]+add[pos[l]]);
int t = ask(l + 1, r, phi[p]);
if(t > p ||flag ) t = t%phi[p] + phi[p], flag = 0;
return power(a[l]+add[pos[l]], t, p);
}
signed main()
{
freopen("zzq.in","r",stdin);
freopen("zzq.out","w",stdout);
n = read();
m = read();
for(int i = 1; i <= n; i++)
a[i] = read();
yych();
zh_dou();
while(m--)
{
opt = read();xx = read(); yy = read(); zz = read();
if(opt == 1)
chenge(xx, yy, zz);
else
flag = 0,//每次都要赋0,(会挂)
printf("%lld\n", ask(xx, yy, zz)%zz);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具