菜
说在前面
神仙OJ!
嘟嘟噜
mayuri.cpp/in/out
Time Limit: 2s
Memory Limit: 512MB
开启 -O2 优化
开启无限栈
1.1 Description
由于众所周知的原因, 冈部一直欠真由理一串香蕉.
为了封上真由理的嘴, 冈部承诺只要真由理回答出这个问题, 就给她买一车的香蕉:
一开始有 n 个人围成一个圈, 从 1 开始顺时针报数, 报出 m 的人被机关处决. 然后下一个人再从 1 开始报数, 直到只剩下一个人.
红莉栖: “这不就是约瑟夫问题吗…”
伦太郎: “助手你给我闭嘴!”
真由理虽然已经晕头转向了, 但听到有一车的香蕉, 两眼便放出了光芒. “那个呢, 真由氏很想要一车子的香蕉呢. 如果可以帮帮我的话, 我可以把一些香蕉分给你哟, 诶
嘿嘿. 拜托你啦.”
1.2 Input Format
第一行一个整数 T, 表示数据组数.
接下来 T 行, 每行两个整数 n, m.
1.3 Output Format
对于每组数据, 输出一行一个整数, 表示幸存者的编号.
1.4 Sample
1.4.1 Input
5
4 6
2 8
2 9
8 8
7 9
1.4.2 Output
3
1
2
4
7
1.5 Constraints
1.6 分析
经典的约瑟夫问题。
1.7 代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
inline void Read(ll &p)
{
p=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9')
p=p*10+c-'0',c=getchar();
}
ll T,n,m,ans;
int main()
{
freopen("mayuri.in","r",stdin);
freopen("mayuri.out","w",stdout);
Read(T);
while(T--)
{
Read(n),Read(m),ans=0;
for(ll i=1;i<=n;i++)
{
ll k=min((i-ans)/m-1,n-i-1);
if(k>0 && k<n) ans+=k*m,i+=k;
(ans+=m)%=i;
}
printf("%lld\n",ans+1);
}
}
天才绅士少女助手克里斯蒂娜
总感觉那个助手崩掉了……
2.6 分析
瞪了15min发现是 叉 积 ! ! ! ! ! \LARGE \LARGE 叉积!\raisebox{0.625cm}{\LARGE!}\raisebox{1.25cm}{\LARGE!}\raisebox{2.5cm}{\LARGE!}\raisebox{5cm}{\LARGE!} 叉积!!!!!
叉积就是
x
1
y
2
−
x
2
y
1
x_1y_2-x_2y_1
x1y2−x2y1。
叉积的平方就是
x
1
2
y
2
2
+
x
2
2
y
1
2
−
2
x
1
y
1
x
2
y
2
x_1^2y_2^2+x_2^2y_1^2-2x_1y_1x_2y_2
x12y22+x22y12−2x1y1x2y2。
于是
a
n
s
=
∑
i
=
l
r
∑
j
=
i
+
1
r
(
x
i
2
y
j
2
+
x
j
2
y
i
2
−
2
x
i
y
i
x
j
y
j
)
=
∑
i
=
l
r
∑
j
=
i
+
1
r
x
i
2
y
j
2
+
∑
i
=
l
r
∑
j
=
i
+
1
r
x
j
2
y
i
2
−
∑
i
=
l
r
∑
j
=
i
+
1
r
2
x
i
y
i
x
j
y
j
=
∑
i
=
l
r
∑
j
=
l
r
[
i
!
=
j
]
×
x
i
2
y
j
2
−
∑
i
=
l
r
∑
j
=
l
r
[
i
!
=
j
]
×
x
i
y
i
x
j
y
j
=
∑
i
=
l
r
x
i
2
(
∑
j
=
l
r
y
j
2
−
y
i
2
)
−
(
∑
i
=
l
r
x
i
y
i
(
∑
j
=
l
r
x
j
y
j
−
x
i
y
i
)
)
=
∑
i
=
l
r
x
i
2
∑
j
=
l
r
y
j
2
−
∑
i
=
l
r
x
i
2
y
i
2
−
(
∑
i
=
l
r
x
i
y
i
∑
j
=
l
r
x
j
y
j
−
∑
i
=
l
r
x
i
2
y
i
2
)
=
∑
i
=
l
r
x
i
2
×
∑
i
=
l
r
y
i
2
−
(
∑
i
=
l
r
x
i
y
i
)
2
ans = \sum \limits_{i=l}^{r} \sum \limits_{j=i+1}^r (x_i^2y_j^2+x_j^2y_i^2-2x_iy_ix_jy_j) \\ = \sum \limits_{i=l}^r \sum \limits_{j=i+1}^r x_i^2y_j^2 + \sum \limits_{i=l}^r \sum \limits_{j=i+1}^r x_j^2y_i^2 - \sum \limits_{i=l}^r \sum \limits_{j=i+1}^r 2x_iy_ix_jy_j \\ = \sum \limits_{i=l}^r \sum \limits_{j=l}^r [i!=j]\times x_i^2y_j^2 - \sum \limits_{i=l}^r \sum \limits_{j=l}^r [i!=j]\times x_iy_ix_jy_j \\ =\sum \limits_{i=l}^r x_i^2 (\sum \limits_{j=l}^r y_j^2 -y_i^2) - (\sum \limits_{i=l}^r x_iy_i (\sum \limits_{j=l}^r x_jy_j - x_iy_i)) \\ = \sum \limits_{i=l}^r x_i^2 \sum \limits_{j=l}^r y_j^2 - \sum \limits_{i=l}^r x_i^2y_i^2 - (\sum \limits_{i=l}^r x_iy_i \sum \limits_{j=l}^r x_jy_j - \sum \limits_{i=l}^r x_i^2 y_i^2) \\ = \sum \limits_{i=l}^r x_i^2\times \sum \limits_{i=l}^ry_i^2 - (\sum \limits_{i=l}^r x_iy_i)^2
ans=i=l∑rj=i+1∑r(xi2yj2+xj2yi2−2xiyixjyj)=i=l∑rj=i+1∑rxi2yj2+i=l∑rj=i+1∑rxj2yi2−i=l∑rj=i+1∑r2xiyixjyj=i=l∑rj=l∑r[i!=j]×xi2yj2−i=l∑rj=l∑r[i!=j]×xiyixjyj=i=l∑rxi2(j=l∑ryj2−yi2)−(i=l∑rxiyi(j=l∑rxjyj−xiyi))=i=l∑rxi2j=l∑ryj2−i=l∑rxi2yi2−(i=l∑rxiyij=l∑rxjyj−i=l∑rxi2yi2)=i=l∑rxi2×i=l∑ryi2−(i=l∑rxiyi)2
我太懒了,连KATEX都是copy来的
2.7 代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
//typedef long long int;
inline void Read(int &p)
{
p=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9')
p=p*10+c-'0',c=getchar();
}
const int MAXN=1002030,mod=20170927;
int n,m,opt,u,v,w,x[MAXN],y[MAXN];
inline int lowbit(int x){return x&(-x);}
struct BIT
{
int bit[MAXN];
inline void update(int pos,int del){while(pos<=n) (bit[pos]+=del)%=mod,pos+=lowbit(pos);}
inline int getsum(int pos){int ans=0; while(pos) (ans+=bit[pos])%=mod,pos-=lowbit(pos); return ans;}
inline int query(int lef,int rig){return getsum(rig)-getsum(lef-1);}
}arr[3];
int main()
{
freopen("kurisu.in","r",stdin);
freopen("kurisu.out","w",stdout);
Read(n),Read(m);
for(int i=1;i<=n;i++) Read(x[i]),Read(y[i]),arr[0].update(i,1ll*x[i]*x[i]%mod),arr[1].update(i,1ll*y[i]*y[i]%mod),arr[2].update(i,1ll*x[i]*y[i]%mod);
while(m--)
{
Read(opt);
if(opt==1) Read(u),Read(v),Read(w),arr[0].update(u,1ll*v*v%mod-1ll*x[u]*x[u]%mod),arr[1].update(u,1ll*w*w%mod-1ll*y[u]*y[u]%mod),arr[2].update(u,1ll*v*w%mod-1ll*x[u]*y[u]%mod),x[u]=v,y[u]=w;
else Read(u),Read(v),w=arr[2].query(u,v),printf("%d\n",((1ll*arr[0].query(u,v)*arr[1].query(u,v)-1ll*w*w)%mod+mod)%mod);
}
}
2.8 说在后面
我之前全文用的long long,T惨了,2.020s望洋兴叹。然后换回int以后就能节省1s左右。
凤凰院凶真
凤凰院凶真
okarin.cpp/in/out
Time Limit: 1s
Memory Limit: 512MB
不开启 -O2 优化
Special Judge
3.1 Description
α 世界线.
凤凰院凶真创立了反抗 SERN 统治的组织 “瓦尔基里”. 为了脱离 α 线, 他需要制作一个世界线变动率测量仪.
测量一个世界线相对于另一个世界线的变动率, 实质上就是要求出这两个世界线的最长公共合法事件序列.
一个世界线的事件逻辑序列是一个正整数序列, 第 k 个数表示第 k 个事件发生的时间.
对于一个世界线, 一个合法的事件序列是事件逻辑序列的一个子序列, 满足时间严格递增.
现在, 对于两个不同的世间线 α, β, 求出最长的一个事件序列, 满足这个序列在 α, β 世界线中均是合法的. 这个序列也就是之前提到过的最长公共合法事件序列.
3.2 Input Format
第一行一个整数 n, 表示 α 世界线的事件个数.
第二行 n 个整数 a1, a2, …, an, 表示 α 世界线的事件逻辑序列.
第三行一个整数 m, 表示 β 世界线的事件个数.
第四行 m 个整数 b1, b2, …, bm, 表示 β 世界线的事件逻辑序列.
3.3 Output Format
第一行一个整数 k, 表示最长公共合法事件序列的长度.
第二行 k 个整数, 表示最长公共合法事件序列. 如果有多解, 输出任意一个.
3.4 Sample
3.4.1 Input
5
1 4 2 5 1
4
1 1 2 4
3.4.2 Output
2
1 4
5
3.5 Constraints
无论执迷过去
还是叹息未来
皆是不准有丝毫误算的必然
所以本题将捆绑测试. 也就是说, 只有你通过一个子任务内的所有测试点, 才能获得该子任务的全部分数, 否则得 0 分.
3.6 分析
最长公共上升子序列板子题。
虽然我也没敲过这板子。
3.7代码
#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
inline void Read(int &p)
{
p=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9')
p=p*10+c-'0',c=getchar();
}
const int MAXN=5024;
stack<int>S;
int n,m,arr[MAXN],brr[MAXN],dp[MAXN][MAXN],pre[MAXN][MAXN],pos=1;
int main()
{
freopen("okarin.in","r",stdin);
freopen("okarin.out","w",stdout);
Read(n); for(int i=1;i<=n;i++) Read(arr[i]);
Read(m); for(int i=1;i<=m;i++) Read(brr[i]);
memset(pre,-1,sizeof pre);
for(int i=1;i<=n;++i)
{
int v=0,k=0;
for(int j=1;j<=m;++j)
{
dp[i][j]=dp[i-1][j];
if(brr[j]<arr[i] && v<dp[i-1][j]) v=dp[i-1][j],k=j;
if(arr[i]==brr[j]) dp[i][j]=v+1,pre[i][j]=k;
}
}
for(int i=1;i<=n;++i) if(dp[n][pos]<dp[n][i]) pos=i;
printf("%d\n",dp[n][pos]);
if(dp[n][pos]!=0)
{
for(int i=n;i>=1;i--) if(pre[i][pos]!=-1) S.push(arr[i]),pos=pre[i][pos];
while(!S.empty()) printf("%d ",S.top()),S.pop();
puts("");
}
}
说在后面
想找个乔瑟夫的图我容易吗?
(龙舌兰?)