noip12
T1
类似于昨天的t3,先用单调栈求出管控区间,然后暴力求解30pts
我没取模还没开longlong,然后就爆0了
正解:
- 仍然是用单调栈求一下区间,用线段树维护一下余数,对于i所对应的区间\([l_{i},r_{i}]\) ,当然是去枚举离i近的,剩下的用线段树求解,线段树要用动态开点,不然空间会炸。
Code
#include<cstdio>
#define K 1000010
#define MAX 300010
#define re register
#define int long long
namespace OMA
{
int n,k,ans;
int a[MAX],sum[MAX];
int root[K];
int top,L[MAX],R[MAX],sta[MAX];
struct Segmnet_Tree
{
int tot;
struct TREE
{
int res;
int ls,rs;
}st[K*50];
inline void Push_up(int p)
{ st[p].res = st[st[p].ls].res+st[st[p].rs].res; }
inline void insert(int &p,int l,int r,int pos)
{
p = (!p)?++tot:p;
if(l==r)
{ st[p].res = 1; return ; }
int mid = (l+r)>>1;
if(pos<=mid)
{ insert(st[p].ls,l,mid,pos); }
else
{ insert(st[p].rs,mid+1,r,pos); }
Push_up(p);
}
inline int query(int p,int l,int r,int lp,int rp)
{
if(l<=lp&&rp<=r)
{ return st[p].res; }
int sum = 0,mid = (lp+rp)>>1;
if(l<=mid)
{ sum += query(st[p].ls,l,r,lp,mid); }
if(r>mid)
{ sum += query(st[p].rs,l,r,mid+1,rp); }
return sum;
}
}Tree;
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
inline void STACK()
{
for(re int i=1; i<=n; i++)
{
while(top&&a[sta[top]]<=a[i])
{ R[sta[top--]] = i-1; }
L[i] = sta[top]+1;
sta[++top] = i;
}
while(top)
{ R[sta[top--]] = n; }
}
signed main()
{
n = read(),k = read();
for(re int i=1; i<=n; i++)
{ (sum[i] = sum[i-1]+(a[i] = read())%k) %= k; }
STACK();
for(re int i=1; i<=n; i++)
{ a[i] %= k; Tree.insert(root[sum[i]],1,n,i); }
for(re int i=1; i<=n; i++)
{
if(L[i]==R[i])
{ continue ; }
if(R[i]-i<i-L[i])
{
for(re int j=i+1; j<=R[i]; j++)
{
if(L[i]-1)
{ ans += Tree.query(root[(sum[j]-a[i]+k)%k],L[i]-1,i-1,1,n); }
else
{
int temp = (sum[j]-a[i]+k)%k;
ans += Tree.query(root[temp],L[i],i-1,1,n);
if(!temp)
{ ans++; }
}
}
if(L[i]-1)
{ ans += Tree.query(root[sum[i-1]],L[i]-1,i-2,1,n); }
else
{
if(i-2)
{ ans += Tree.query(root[sum[i-1]],1,i-2,1,n); }
if(!sum[i-1])
{ ans++; }
}
}
else
{
for(re int j=L[i]; j<=i-1; j++)
{ ans += Tree.query(root[(sum[j-1]+a[i])%k],i,R[i],1,n); }
if(i<R[i])
{ ans += Tree.query(root[sum[i]],i+1,R[i],1,n); }
}
}
printf("%lld\n",ans);
return 0;
}
}
signed main()
{ return OMA::main();}
T2
式子很好推,结果被我一顿乱搞+瞎取模取成了10pts。
首先正难则反(来自数学课),可以先求出变量互不相同时的式子
\]
然后我就码了个快速幂,求阶乘逆元gcd,一顿乱搞30pts->10pts
此时,我自己造了几个数据,发现显然不对,于是去想如何改一下。没想出来,交了个10pts。
正解:
推出式子后,考虑约分,发现只能约2及其倍数。所以去找有多少个2。
然后有个定理 \(2^{n}-a\)和\(a\) 这俩东西中,2的个数是相等的,所以找分子中2的个数,就转换成了去找 \((m-1)!\) 中2的个数,这个可以 \(O(logm)\) 求解。
对于\(m>mod\) 此时一定有一个数为mod的倍数,所以分子为0,但答案并非这个,因是%mod意义下的0,所以直接去计算分母就好了。
\(m\le mod\) 的话,直接暴力计算就好了。
Code
#include<cstdio>
#define MAX 1000100
#define re register
#define int long long
namespace OMA
{
int n,m,a,b;
int inv,c,cnt=63;
const int p = 1e6+3;
inline int quickpow(int a,int b)
{
int ans = 1;
while(b)
{
if(b&1)
{ ans = ans*a; }
a = a*a;
b >>= 1;
}
return ans;
}
signed main()
{
scanf("%lld%lld",&n,&m);
n %= p-1;
int tmp1 = 1,tmp2 = 0;
while(cnt--)
{ tmp1 <<= 1; if(tmp1>=m){ break; } (tmp2 += (m-1)/tmp1) %= p-1; }
c = quickpow(2,n),inv = quickpow(quickpow(2,tmp2),p-2);
b = quickpow(c,(m-1)%(p-1))*inv%p;
if(m<=p)
{
a = inv;
for(re int i=1; i<=m; i++)
{ (a *= c-i) %= p; }
a = ((b-a)%p+p)%p;
printf("%lld %lld\n",a,b);
}
else
{ printf("%lld %lld\n",b,b); }
return 0;
}
}
signed main()
{ return OMA::main(); }
T3
考试的时候写了个f**k大模拟+贪心,还过了自己造的hack数据,结果程序输出全是-1 10pts好成绩
考试做法错误是显然的,比如1 0 0 0 1,我的码会输出-1,因为是从前往后扫,出现次数超过1就换下一个值,顾前不顾后,wa也正常。
正解:
我们可以设二元组(a,b),表示当前位置上的数为a,其连续的长度为b。分别设两个 \(up\)和\(down\),up为能填的最大值,down为最小值,求up应该尽量往上,down相反。
最大值即为 \(up[n].a\),序列倒着就能求出来。具体实现见code。
Code
#include<cstdio>
#define MAX 200010
#define re register
namespace OMA
{
int n,m,cnt[MAX];
int a[MAX],ans[MAX];
struct pair
{ int a,b; };
pair up[MAX],down[MAX];
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
inline int min(int a,int b)
{ return a<b?a:b; }
signed LZk()
{
n = read();
for(re int i=1; i<=n; i++)
{ a[i] = read(); }
a[1] = 1;
up[1] = down[1] = (pair){1,1};
for(re int i=2; i<=n; i++)
{
up[i] = (pair){up[i-1].a,up[i-1].b+1};
down[i] = (pair){down[i-1].a,down[i-1].b+1};
if(up[i].b>2)
{ up[i] = (pair){up[i].a+1,1}; }
if(down[i].b>5)
{ down[i] = (pair){down[i].a+1,1}; }
if(a[i])
{
if(up[i].a>a[i])
{ up[i] = (pair){a[i],2}; }
if(down[i].a<a[i])
{ down[i] = (pair){a[i],1}; }
if(up[i].a<a[i]||a[i]<down[i].a)
{ printf("-1\n"); return 0; }
}
}
if(up[n].b==1)
{ up[n] = (pair){up[n-1].a,up[n-1].b+1}; }
printf("%d\n",up[n].a);
a[n] = up[n].a,cnt[up[n].a]++;
for(re int i=n-1; i>=1; i--)
{
if(!a[i])
{
int tmp = min(a[i+1],up[i].a);
if(cnt[tmp]==5)
{ tmp--; }
a[i] = tmp;
}
cnt[a[i]]++;
}
for(re int i=1; i<=n; i++)
{ printf("%d ",a[i]); }
return 0;
}
}
signed main()
{ return OMA::LZk(); }
noip12的更多相关文章
- 20210712 noip12
考场 第一次和 hzoi 联考,成功给 sdfz 丢人 尝试戴耳罩,发现太紧了... 决定改变策略,先用1h看题,想完3题再写. T1 一下想到枚举最大值,单调栈求出每个点能作为最大值的区间,然后以这 ...
随机推荐
- 【重学Java】IO流
IO流的UML类图 File类 File类概述和构造方法[应用] File类介绍 它是文件和目录路径名的抽象表示 文件和目录是可以通过File封装成对象的 对于File而言,其封装的并不是一个真正存在 ...
- Nacos配置中心功能
目录 Nacos的配置管理模型 命名空间(Namespace) 配置分组(Group) 配置集(Data ID) 配置项 一个最佳实践 命名空间管理 配置管理 参考 Nacos的配置管理模型 对于Na ...
- STM32笔记一
1.脉冲宽度调制是(PWM):用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量.通信到功率控制与变换的许多领域中.一般用于直流电机调速. 2.外部中断:外部中断是单片机实 ...
- 《手把手教你》系列技巧篇(八)-java+ selenium自动化测试-元素定位大法之By id(详细教程)
1.简介 从这篇文章开始,要介绍web自动化核心的内容,也是最困难的部分了,就是:定位元素,并去对定位到的元素进行一系列相关的操作.想要对元素进行操作,第一步,也是最重要的一步,就是要找到这个元素,如 ...
- python使用笔记14--商品管理小练习
1 import json 2 import pymysql 3 IP = '127.0.0.1' 4 PORT = 3306 5 USER_NAME = 'root' 6 PASSWORD = '1 ...
- 前端开发入门到进阶第三集【获取cookie然后单点登录后重定向】
/* var token ;//https://blog.csdn.net/qq_29207823/article/details/81745757 if( $.cookie('BBK_TOKEN') ...
- 记录一些css奇淫技巧
文本两端对齐 文字在固定宽度内两端对齐 text-align: justify; text-align-last: justify; 滤镜filter 元素(经常用作图片)置灰效果,类似disable ...
- MySQL检查与性能优化示例脚本
最近在玩python,为了熟悉一下python,写了个mysql的检查与性能优化建议的脚本. 虽然,真的只能算是一个半成残次品.也拿出来现眼一下. 不过对于初学者来说,还是有一定的参考价值的.比如说如 ...
- HTTP协议GET方法传参最大长度理解误区
结论 HTTP 协议未规定GET和POST的长度 GET的最大长度是因为浏览器和WEB服务器显示了URI的长度 不同浏览器和WEB服务器,限制的最大长度不同 若要支持IE,则最大长度为2083 byt ...
- (python函数02)列表生成式
(python函数02)列表生成式 示例代码 num = [i for i in range(1, 10)] print(num) num = [i for i in range(1, 10) ...
