6.15 NOI 模拟
\(T1\ ckr\)与平方数
不会吧,不会吧,真有人不会积分,好吧,我真的一点也不会。。。
基本公式\(:\)
\(1.\)多项式定积分的计算方法
\\
\int_{a}^{b}=\sum_{i=0}^n\frac{(b^{i+1}-a^{i+1})c_i}{i+1}
\]
\(2.\)换元积分法
设\(I\subseteq \R\)为一个区间,\(\varphi:[a,b]\rightarrow I\)是一个导数可积的函数(不是数论函数)。设\(f:I\rightarrow \R\)是一个连续函数。(说人话就是连续可导)
\]
考虑证明:
设\(F'(x)=f(x)\)
\\
u=\varphi(x)
\\
{\rm d}[F(u)]={\rm d}[F(\varphi(x))]=f(\varphi(x))\varphi'(x) {\rm d}x
\\
\int f(\varphi(x))\varphi'(x) {\rm d}x=\int f(u){\rm d}u
\]
\(3.\)分部积分法
设\(u=u(x),{\rm d}u=u'(x){\rm d}x,v=v(x),{\rm d}v=v'(x){\rm d}x\)
\]
考虑证明:
\\
[u(x)v(x)]'-u'(x)v(x)=u(x)v'(x)
\]
两边分别积分即可
\]
然后做这道题:
算法一
假如我们只看懂了第一个式子(就像我一样)
暴力卷积求出每一项系数积回去即可
#define Eternal_Battle ZXK
#include<bits/stdc++.h>
#define int long long
#define MAXN 3005
using namespace std;
const int mod=2147483647;
int a[MAXN],b[MAXN],c[MAXN<<1],fx[MAXN<<1],inv[MAXN<<1];
int N,s,t,x;
void sol(int n,int m)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
a[0]=s; a[1]=1;
b[0]=t; b[1]=1;
for(int i=2;i<=n;i++)
{
for(int j=i;j>=1;j--)
{
a[j]=(a[j-1]+a[j]*s%mod)%mod;
}
(a[0]*=s)%=mod;
}
for(int i=2;i<=m;i++)
{
for(int j=i;j>=1;j--)
{
(b[j]=b[j-1]+b[j]*t%mod)%=mod;
}
(b[0]*=t)%=mod;
}
memset(c,0,sizeof(c));
for(int i=0;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
(c[i+j]+=a[i]*b[j]%mod)%=mod;
}
}
int res=0;
for(int i=0;i<=n+m;i++)
{
res=(res+(fx[i+1]*c[i])%mod*inv[i+1]%mod)%mod;
}
printf("%lld ",res);
}
void Init()
{
fx[0]=1; fx[1]=x;
inv[0]=inv[1]=1;
for(int i=2;i<MAXN;i++)
{
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
fx[i]=fx[i-1]*x%mod;
}
}
signed main()
{
scanf("%lld%lld%lld%lld",&N,&s,&t,&x);
Init();
for(int i=1;i*i<=N;i++)
{
for(int j=1;j*j<=N;j++)
{
sol(i*i,j*j);
}
puts("");
}
}
算法二
使用\(FFT\)计算系数,分数不变
算法三
\(s=t\),可以直接套用公式
\]
算法四
我们看懂了第二条和第三条公式,但是我们不想往下推了!
\(x\leftarrow x+s\)
\]
考虑对上面这个东西分步积分
\]
后面的这个式子可以递归,可以做到\(O(n+m)\)
算法EX
这时候,你想\(A\)掉这道题
#include<bits/stdc++.h>
#define mod 2147483647
#define int long long
#define MAXN 200002
using namespace std;
int N,s,t,x0;
int pt[MAXN],fac[MAXN],inv[MAXN],invs[MAXN],pows[MAXN],powt[MAXN],spow[MAXN],tpow[MAXN];
int my_pow(int x,int y)
{
int res=1;
while(y)
{
if(y&1) res=res*x%mod;
x=x*x%mod;
y=(y>>1);
}
return res;
}
int Inv(int x)
{
return my_pow(x,mod-2);
}
void Init()
{
fac[0]=1;
for(int i=1;i<MAXN;++i) fac[i]=fac[i-1]*i%mod;
inv[MAXN-1]=Inv(fac[MAXN-1]);
pows[0]=powt[0]=spow[0]=tpow[0]=1;
for(int i=MAXN-2;i>=0;--i) inv[i]=inv[i+1]*(i+1)%mod;
int tmp=s-t;
tmp+=(tmp>>31)&mod;
for(int i=1;i<MAXN;++i)
{
pows[i]=pows[i-1]*(x0+s)%mod;
powt[i]=powt[i-1]*(x0+t)%mod;
spow[i]=spow[i-1]*s%mod;
tpow[i]=tpow[i-1]*t%mod;
invs[i]=inv[i]*fac[i-1]%mod;
pt[i]=pt[i-1]+tmp-mod;pt[i]+=pt[i]>>31&mod;
}
}
signed main()
{
scanf("%lld %lld %lld %lld",&N,&s,&t,&x0);
Init();
for(int i=1;i*i<=N;++i)
{
int res=(pows[i*i+1]-spow[i*i+1])*invs[i*i+1]%mod;
for(int j=1;j<=N;++j)
{
(res=pows[i*i+1]*powt[j]%mod+pt[j]*(mod-res)%mod)%=mod;
(res+=(mod-spow[i*i+1])*tpow[j])%=mod;
res%=mod;
res+=res>>63&mod;res+=res>>63&mod;
(res*=invs[i*i+j+1])%=mod;
if((int)sqrt(j)*(int)sqrt(j)==j)
cout<<(res%mod+mod)%mod<<" ";
}
cout<<endl;
}
}
\(T2\ math\)
考虑一下单位根的性质
\left\{
\begin{array}{**lr**}
n\ \ \ \ n \mid k
\\
0\ \ \ \ n\nmid k&
\end{array}
\right.
\]
有多项式
\]
把\(x^n=1\)的根\(r\)全部带进去,\(\sum f(r)\)
\]
我们要求所有的不超过\(n\)次的单位根,重复的只求一次的\(\sum f(r)\)
设本原单位根为\(w_n^k,\gcd(n,k)=1\)
\(F(i)=\sum f(r)[r\)是\(i\)次本原单位根\(]\)
\(G(i)=\sum f(r)[r\)是\(i\)次单位根\(]\)
\]
考虑证明:
我们每个单位根第一次出现肯定在因数的位置,感觉这个东西和\(\sum_{d|n}\varphi(d)=n\)有点像
\\
F=G/I
\]
考虑用杜教筛解决
#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define rint register int
#define LL __int128
#define N 10000010
using namespace std;
char buf[1<<21],*p1,*p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
int n,k,a[N],tot;
ll idn[N],IDN[N];
ll ID(ll x)
{
if(x<=n/x) return idn[x]=idn[x]?idn[x]:++tot;
else return IDN[n/x]=IDN[n/x]?IDN[n/x]:++tot;
}
bitset<N> sh;
ll prime[N],phi[N],qzp[N],f[N],mu[N],qzm[N];
int cnt;
ll phis[N],mus[N];
ll Phi(ll x)
{
if(x<=N-10) return qzp[x];
if(phis[ID(x)]) return phis[ID(x)];
ll ans=(x+1)*x/2;
for(ll l=2,r;l<=x;l=r+1)
{
r=x/(x/l);
ans-=(r-l+1)*Phi(x/l);
}
return phis[ID(x)]=ans;
}
int Mu(rint x)
{
if(x<=N-10) return qzm[x];
if(mus[ID(x)]) return mus[ID(x)];
rint ans=1;
for(rint l=2,r;l<=x;l=r+1)
{
r=x/(x/l);
ans-=(r-l+1)*Mu(x/l);
}
return mus[ID(x)]=ans;
}
void write(LL x)
{
if(x/10) write(x/10);
putchar(x%10+'0');
}
inline int read()
{
rint 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<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
signed main()
{
n=read(),k=read();
qzp[1]=phi[1]=mu[1]=qzm[1]=1;
for(ll i=2;i<=N-10;++i)
{
if(!sh[i])
{
prime[++cnt]=i;
phi[i]=i-1;
mu[i]=-1;
}
for(rint j=1;j<=cnt&&prime[j]*i<N;++j)
{
sh[i*prime[j]]=1;
if(i%prime[j])
{
phi[i*prime[j]]=phi[i]*phi[prime[j]];
mu[i*prime[j]]=-mu[i];
}
else
{
phi[i*prime[j]]=phi[i]*prime[j];
mu[i*prime[j]]=0;
break;
}
}
}
for(rint i=2;i<=N-10;++i) qzp[i]=qzp[i-1]+phi[i],qzm[i]=qzm[i-1]+mu[i];
for(rint i=0;i<=k;++i) a[i]=read();
LL ans=(LL)a[0]*Phi(n);
for(rint i=1;i<=k;++i) f[i]=(LL)i*Mu(n/i);
for(rint i=1;i<=cnt&&prime[i]<=k;++i)
for(rint j=1;j<=k/prime[i];++j)
f[j*prime[i]]+=f[j];
for(rint i=1;i<=k;++i) ans+=(LL)f[i]*a[i];
if(ans<0) ans=-ans,putchar('-');
write(ans);
}
\(T3\ viru\)
暴力可以拿\(90pts\)
考虑对于每种颜色,求哪些矩阵不能包含。
考虑如何\(O(n^3)\)
首先根号分治,出现次数小的直接暴力,出现次数大的考虑扫一遍
扫的话,考虑枚举下边界,左右边界,我们需要求的是,每一列最靠下的位置在哪。
可以拿到\(90pts\)(粘一下其他老哥代码)
#pragma GCC optimize(2)
%:pragma GCC optimize(3)
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;
const int N=1510;
int n,m,w[N],h[N],up[N][N];
bool a[N][N];stack<int> s;
vector<int> v[N*N];
long long ans;
void calc1(int p){
sort(v[p].begin(),v[p].end());
for(int i=0;i<v[p].size();i++){
int x=v[p][i]/n,y=v[p][i]%n;
int l=0,r=n-1,last=x;
for(int j=i+1;j<v[p].size();j++){
int _x=v[p][j]/n,_y=v[p][j]%n;
ans+=1ll*(_x-last)*(r-y+1)*(y-l+1)*(x+1);
if(_y<=y)l=max(_y+1,l);
if(_y>=y)r=min(_y-1,r);
last=_x;
}
ans+=1ll*(n-last)*(r-y+1)*(y-l+1)*(x+1);
}
return;
}
void calc2(int p){
for(int i=0;i<v[p].size();i++)
a[v[p][i]/n][v[p][i]%n]=1;
ans+=1ll*n*n*(n+1)*(n+1)/4;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(a[i][j])up[i][j]=i+1;
else if(i)up[i][j]=up[i-1][j];
else up[i][j]=0;
h[j]=i-up[i][j]+1;w[j]=1;
while(!s.empty()&&h[j]<=h[s.top()]){
ans-=1ll*h[s.top()]*w[s.top()]*w[j];
w[j]+=w[s.top()];s.pop();
}
s.push(j);
}
int len=1;
while(!s.empty())
ans-=1ll*h[s.top()]*w[s.top()]*len,len+=w[s.top()],s.pop();
}
for(int i=0;i<v[p].size();i++)
a[v[p][i]/n][v[p][i]%n]=0;
return;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
for(int j=0,x;j<n;j++){
scanf("%d",&x);
// x=rand()%m;
v[x].push_back(i*n+j);
}
for(int i=1;i<=n*n;i++)
if(v[i].size()<=n)calc1(i);
else calc2(i);
printf("%lld\n",ans);
return 0;
正解的话需要笛卡尔树
#include<bits/stdc++.h>
#define ls t[x].l
#define rs t[x].r
using namespace std;
struct node{
int fa,l,r,L,R,val,s;
void init()
{
fa=l=r=L=R=val=s=0;
}
}t[2250011];
int n,cnt,sum,rt,la;
int col[2250011],id[2250011],x[2250011],y[2250011];
int exis[2250011],p[2250011],g[2250011];
long long ans;
bool cmp(int a,int b)
{
if(col[a]==col[b]) return a<b;
return col[a]<col[b];
}
void push_up(int x)
{
t[x].L=ls?t[ls].L:p[x-1];
t[x].R=rs?t[rs].R:p[x+1];
t[x].s=t[ls].s+t[rs].s+t[x].val*(p[x]-t[x].L)*(t[x].R-p[x]);
}
int build(int f,int l,int r)
{
if(l>r)return 0;
int mid=(l+r)>>1;
t[mid].fa=f,t[mid].L=p[l-1],t[mid].R=p[r+1];
t[mid].l=build(mid,l,mid-1),t[mid].r=build(mid,mid+1,r);
return mid;
}
void re(int x)
{
int f=t[x].fa,gf=t[f].fa;
if(gf)
{
if(t[gf].l==f) t[gf].l=x;
if(t[gf].r==f) t[gf].r=x;
}
if(t[f].l==x) t[rs].fa=f,t[f].l=rs,rs=f;
else t[ls].fa=f,t[f].r=ls,ls=f;
t[f].fa=x,t[x].fa=gf;
push_up(f);
}
void tar(int x,int c)
{
t[x].val=c;
int f=0;
while(f=t[x].fa)
{
if(t[f].val>=t[x].val) break;
re(x);
}
while(1)
{
push_up(x);
if(!t[x].fa) return rt=x,void();
x=t[x].fa;
}
}
void gets(int l,int r)
{
cnt=sum=0;
for(int i=l;i<=r;++i)
{
cnt++;
x[cnt]=((id[i]-1)/n)+1;
y[cnt]=((id[i]-1)%n)+1;
if(!exis[y[cnt]]) exis[y[cnt]]=1,p[++sum]=y[cnt];
}
p[0]=0,p[sum+1]=n+1;
sort(p+1,p+sum+1);
}
void chu_ans(int l,int r)
{
gets(l,r);
for(int i=1;i<=sum;++i) t[i].init();
for(int i=1;i<=sum;++i) g[p[i]]=i;
rt=build(0,1,sum),la=0;
for(int i=1;i<=cnt;++i)
{
ans=ans+1ll*t[rt].s*(x[i]-1-la);
la=x[i]-1;
tar(g[y[i]],x[i]);
}
ans=ans+1ll*t[rt].s*(n-la);
for(int i=1;i<=sum;++i) exis[p[i]]=0;
}
//char buf[1<<21],*p1,*p2;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
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<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int main()
{
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
n=read();
for(int i=1;i<=n*n;++i) col[i]=read();
int all_the_same=col[1];
for(int i=1;i<=n*n;++i) if(col[i]!=all_the_same) all_the_same=0;
// cerr<<"ww";
if(all_the_same) cout<<1ll*n*(n+1)*n*(n+1)/4,exit(0);
for(int i=1;i<=n*n;++i) id[i]=i;
sort(id+1,id+n*n+1,cmp);
for(int l=1,r;l<=n*n;l=r+1)
{
r=l;
while(r<n*n&&col[id[r+1]]==col[id[l]]) ++r;
chu_ans(l,r);
}
cout<<ans;
}
6.15 NOI 模拟的更多相关文章
- 5.30 NOI 模拟
$5.30\ NOI $模拟 高三大哥最后一次模拟考了,祝他们好运 \(T1\)装箱游戏 显然可以将四种字母之间的空缺当做状态枚举 那么这道题就很显然了 #include<bits/stdc++ ...
- 5.23 NOI 模拟
$5.23\ NOI $模拟 \(T1\)简单的计算几何题 \(zjr:\)我当时没改,那么自己看题解吧 倒是有个简单的随机化方法(能获得\(72pts,\)正确性未知)\(:\) 随机两条切椭圆的平 ...
- 5.6 NOI模拟
\(5.6\ NOI\)模拟 明天就母亲节了,给家里打了个电话(\(lj\ hsez\)断我电话的电,在宿舍打不了,只能用教练手机打了) 其实我不是很能看到自己的\(future,\)甚至看不到高三的 ...
- 5.4 NOI模拟
\(5.4\ NOI\)模拟 \(T1\) 想到分讨,但是暴力输出一下方案之后有很多特别的情况要讨论,就弃了... 假设\(a\)是原序列,\(b\)是我们得到的序列 设\(i\)是最长公共前缀,\( ...
- NOI模拟赛(3.15) sequence(序列)
Description 小A有N个正整数,紧接着,他打算依次在黑板上写下这N个数.对于每一个数,他可以决定将这个数写在当前数列的最左边或最右边.现在他想知道,他写下的数列的可能的最长严格上升子序列(可 ...
- NOI 模拟赛 #2
得分非常惨惨,半个小时写的纯暴力 70 分竟然拿了 rank 1... 如果 OYJason 和 wxjor 在可能会被爆踩吧 嘤 T1 欧拉子图 给一个无向图,如果一个边集的导出子图是一个欧拉回路, ...
- 【2019.8.15 慈溪模拟赛 T1】插头(plugin)(二分+贪心)
二分 首先,可以发现,最后的答案显然满足可二分性,因此我们可以二分答案. 然后,我们只要贪心,就可以验证了. 贪心 不难发现,肯定会优先选择能提供更多插座的排插,且在确定充电器个数的情况下,肯定选择能 ...
- 6.28 NOI模拟赛 好题 状压dp 随机化
算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...
- NOI模拟赛 Day1
[考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...
随机推荐
- JavaMetaweblogClient,Metaweblog的java实现-从此上传博客实现全平台
目录 1. 什么是Metaweblog? 2. Metaweblog的应用 3. 如何使用Metaweblog 4. 本项目介绍 4.1 metaweblog与java之间的关系映射 4.2 使用Ja ...
- 渗透:Nmap
Nmap,也就是Network Mapper,最早是Linux下的网络扫描和嗅探工具包. nmap是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端.确定哪些服务运行在哪些连接端,并且推断计算 ...
- Spring Boot下Spring Batch入门实例
一.About Spring Batch是什么能干什么,网上一搜就有,但是就是没有入门实例,能找到的例子也都是2.0的,看文档都是英文无从下手~~~,使用当前最新的版本整合网络上找到的例子. 关于基础 ...
- Git 不识别文件名字母大小写变化
问题 今天为一个项目撰写持续构建计划,撰写 Jenkinsfile 之后进行构建时报错: [2022-05-23 16:54:21] unable to prepare context: unable ...
- Border性质习题与证明
KMP 第一次接触 \(border\) 都是先从 KMP 开始的吧. 思想在于先对于一个串自匹配以求出 fail 指针(也就是 border) 然后就可以在匹配其他串的时候非常自然的失配转移.在此顺 ...
- 【可视化分析案例】用python分析B站Top100排行榜数据
一.数据源 之前,我分享过一期爬虫,用python爬取Top100排行榜: 最终数据结果,是这样的: 在此数据基础上,做python可视化分析. 二.数据读取 首先,读取数据源: # 读取csv数据 ...
- 1.3温度转换(中国大学Mooc-Python 语言程序设计)
温度转换 温度刻画的两种不同体系 1.摄氏度:(中国等世界大多数国家使用) 以1标准大气压下水的结冰点为0度,沸点为100度,将温度进行等分刻画 2.华氏度:(美国.英国等国家使用) 以1标准大气压 ...
- Linux 中递归删除文件
递归删除当前目录下以 .json 结尾的文件 find . -name "*.json" | xargs rm -f find . -name "*.json" ...
- 总结 到 GDOI 2021 这个阶段
截止本蒟蒻第一次体验省选(虽然是普及组) 本蒟蒻已经有了许多收获,却也有很多不足 优点 对一些学过的知识掌握还行 没了 缺点 会却做不出来 有一些题不难,却想不到正解 如 Day2 T1 ,就是移一下 ...
- dubbox、zookeeper BUG记录
主要错误信息: dubbo:com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method... Caused by: com.alib ...