题目
【NOIP提高组模拟1】小L的数列
(File IO): input:seq.in output:seq.out
Time Limits: 1500 ms
Memory Limits: 524288 KB
Description
Input
一行两个整数n和k。
之后1行k个正整数b1…bk。
之后1行k个正整数f1…fk。
Output
输出一个整数表示fn
Sample Input
【样例输入1】
5 4
1 2 3 4
4 3 2 1
【样例输入2】
100000 4
1 2 3 4
12 23 34 45
Sample Output
【样例输出1】
27648
【样例输出2】
33508797
Data Constraint
对于30%的数据,n≤10000.
对于另外20%的数据,bi=1,n≤1000000.
对于另外20%的数据,f[1]…f[k-1]=1.
对于另外20%的数据,k≤30.
对于100%的数据,1≤k≤200,1≤n≤40000000,1≤bi,fi≤998244352.
Hint
样例解释:122333444*4=27648
【NOIP提高组模拟1】梦境
(File IO): input:dream.in output:dream.out
Time Limits: 1000 ms
Memory Limits: 262144 KB
Description
Input
Output
Sample Input
2 2
1 3
2 4
1
3
Sample Output
2
Data Constraint
Hint
【noip提高组模拟1】树
(File IO): input:tree.in output:tree.out
Time Limits: 1000 ms
Memory Limits: 524288 KB
Description
有一棵n个节点的无根树,给出其中的m对点对<x,y>。问有多少条树上的简单路径<u,v>满足该路径上不存在任何一对给出的点对<x,y>。
这里我们认为路径<u,v>和<v,u>是相同的。并且对于题目中给出的点对<x,y>满足x!=y,对于你要计数的路径<u,v>满足u!=v(即单点不算答案)。
Input
第一行两个正整数n,m。
接下来n-1行每行两个正整数u,v描述树上的一条边。
接下来m行每行两个正整数x,y描述一对给出的点对。
(注意,这里我们不保证同样的点对<x,y>不会重复出现)
Output
一行一个整数,表示满足要求的树上简单路径的条数。
Sample Input
8 3
1 2
1 3
4 8
2 4
2 5
3 6
3 7
2 3
4 8
6 7
Sample Output
11
Data Constraint
Hint
满足条件的路径为<1,2>,<1,3>,<1,4>,<1,5>,<1,6>,<1,7>,<2,4>,<2,5>,❤️,6>,❤️,7>,<4,5>。
总结
今天我的发挥不好啊……
看到T1时,我的感受是:哇塞!又是一波推式子,好像挺难的耶!
然后我就暴力直接推
f
k
+
1
,
f
k
+
2
⋯
f
n
f_{k+1},f_{k+2}\cdots f_n
fk+1,fk+2⋯fn,结果推了不到3个数就发现自己推错了!
于是重推,结果又错了……3次后,我放弃(部分分70啊,这不是很好水的吗?)
再看T2,哇塞,好像二分图最大匹配耶!再一看,匈牙利算法的
O
(
n
m
)
O(nm)
O(nm)可能过不了100分,但是没关系!我们有读入优化,我们有O(2)卡常,我们有光速优化,我们有O(fast)犯罪,我们有底层优化和循环展开,我们还有n^2过100000的信心和决心! 部分分有70啊!
看看T3,正解玄学,不会。但是分类讨论可以90啊!接近AC啊!
然后我发现T1好像水不到70耶……
不过没关系,水分加起来一共
50
+
70
+
90
=
210
50+70+90=210
50+70+90=210,拿到这个分数就够了!
水分大作战的号角吹响了……
11:20
我*!T3怎么码了一个小时都没有码完?我之前真是想得太简单了!
哎呀,链和菊花图的情况已经打完了,剩下就不打暴力了,直接打表输出11吧!
赶快自己出个数据……
我*!怎么没输出?
哦!原来是我忘记打printf了。
诶?怎么输出错了?
哦,打错了一个字母!
再运行,天哪,怎么RE了?OMG,11:26了,我要加快速度了!
………………………………
然后就0分了。
咦,T2怎么WA50了?
总结:时间要规划好,不要好高骛远,打题之前要大略地估算一下码量和实现难度。分情况水分的一定要先调完一个再打另外一个,避免狂码1.5小时+后爆〇。
题解
T1
直接推 f 是很难的,于是可以考虑推b。
有一个显然的定理:
a
b
×
a
c
=
a
b
+
c
,
(
a
b
)
c
=
a
b
c
a^b\times a^c=a^{b+c},(a^b)^c=a^{bc}
ab×ac=ab+c,(ab)c=abc,于是可以处理
f
i
f_i
fi由
f
1
,
f
2
⋯
f
k
f_1,f_2\cdots f_k
f1,f2⋯fk分别乘多少得到。
然后就可以矩阵乘法了。
T2
其实这题是最简单的,甚至不用二分图最大匹配,一个贪心即可AC。
可以把转折点从小到大排序,梦境区间按左端点从小到大的顺序排序,然后处理转折点。
如果一个梦境区间的左端点小于等于当前转折点,那么我们把它放入一个按右端点从小到大排序的堆里面。
接下来每次取出堆顶判断一下就可以了。
T3
先把每一个点求dfs序,这样相同子树的点的编号是连续的,处理就方便得多了。
接下来对于每一个询问(u,v)分类讨论:
- 如果u和v在同一条链内,假定u为祖先,那么u的其他子树和子树u以外的所有点都不能与v形成点对;
- 否则,u子树和v子树内的所有点都不能形成点对。
那么,现在问题就转变为如何处理这些不能形成点对的情况了。
可以用矩形来表示这些情况,如果dfn序为
[
x
1
,
x
2
]
[x1,x2]
[x1,x2]和
[
y
1
,
y
2
]
[y1,y2]
[y1,y2]的点不能形成点对,那么就建一个横坐标为
[
x
1
,
x
2
]
[x1,x2]
[x1,x2],纵坐标为
[
y
1
,
y
2
]
[y1,y2]
[y1,y2]的矩形。用扫描线处理出矩形总面积,用
n
(
n
−
1
)
2
\frac{n(n-1)}{2}
2n(n−1)减去即是答案。
CODE
T1
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define P 998244352
#define mod 998244353
#define N 205
ll f[N],a[N][N],ans=1,K;
struct matrix
{
ll a[N][N];
matrix(){memset(a,0,sizeof(a));}
inline matrix operator *(const matrix x)
{
matrix res;
for(int i=1;i<=K;i++)
for(int j=1;j<=K;j++)
for(int k=1;k<=K;k++)
res.a[i][j]=(res.a[i][j]+a[i][k]*x.a[k][j])%P;
return res;
}
}A;
inline matrix mulpow(matrix x,int y)
{
matrix s;int i;
for(i=1;i<=K;i++) s.a[i][i]=1;
while(y)
{
if(y&1) s=s*x;
x=x*x,y>>=1;
}
return s;
}
inline ll numpow(ll x,ll y)
{
ll s=1;
while(y)
{
if(y&1) s=s*x%mod;
x=x*x%mod,y>>=1;
}
return s;
}
int main()
{
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
int n,i,j;
scanf("%d%lld",&n,&K);
for(i=1;i<=K;i++) scanf("%lld",&A.a[K+1-i][K]);
for(i=1;i<=K;i++) scanf("%lld",f+i);
if(n<=K){printf("%lld\n",f[n]);return 0;}
for(i=2;i<=K;i++) A.a[i][i-1]=1;
A=mulpow(A,n-K);
for(i=1;i<=K;i++) ans=ans*numpow(f[i],A.a[i][K])%mod;
printf("%lld\n",ans);
return 0;
}
T2
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC optimize("fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC diagnostic error "-std=c++14"
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 200005
struct interval
{
int l,r;
bool operator <(const interval y)const
{return r>y.r;}
}a[N],temp;
priority_queue<interval>que;
int b[N],n,m;
char ch;bool use[N];
inline char gc()
{
static char buf[N],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x)
{
while(ch=gc(),ch<'0'||ch>'9');x=ch-'0';
while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
bool cmp(interval x,interval y)
{return x.l<y.l||x.l==y.l&&x.r<y.r;}
int main()
{
freopen("dream.in","r",stdin);
freopen("dream.out","w",stdout);
int i,j,ans=0;
read(n),read(m);
for(i=1;i<=n;i++) read(a[i].l),read(a[i].r);
sort(a+1,a+n+1,cmp);
for(i=1;i<=m;i++) read(b[i]);
sort(b+1,b+m+1);
for(i=j=1;i<=m;i++)
{
while(j<=n&&a[j].l<=b[i]) que.push(a[j++]);
if(que.empty()) continue;
else temp=que.top(),que.pop();
while((!que.empty())&&temp.r<b[i]) temp=que.top(),que.pop();
if(temp.r>=b[i]) ans++;
}
printf("%d\n",ans);
return 0;
}
T3
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC optimize("fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC diagnostic error "-std=c++14"
#include<cstdio>
#include<algorithm>
using namespace std;
#define swap(x,y) x^=y,y^=x,x^=y
#define lson k<<1
#define rson k<<1|1
#define N 100005
struct line{int x,yl,yr,num;}a[N<<2];
struct SegmentTree
{
int num[N*17],sum[N*17];
inline void update(int k,int l,int r)
{
if(num[k]) sum[k]=r-l+1;
else if(l==r) sum[k]=0;
else sum[k]=sum[lson]+sum[rson];
}
inline void add(int k,int l,int r,int x,int y,int z)
{
if(x==l&&r==y) num[k]+=z;
else
{
int mid=l+r>>1;
if(y<=mid) add(lson,l,mid,x,y,z);
else if(x>mid) add(rson,mid+1,r,x,y,z);
else add(lson,l,mid,x,mid,z),add(rson,mid+1,r,mid+1,y,z);
}
update(k,l,r);
}
}tree;char ch;
struct EDGE{int end,nex;}edge[N<<1];
inline char gc()
{
static char buf[N],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x)
{
while(ch=gc(),ch<'0'||ch>'9');x=ch-'0';
while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
int fir[N],dfn[N],las[N],f[N][17],s,cnt;
inline bool cmp(line x,line y){return x.x<y.x;}
inline void inc(int x,int y)
{
edge[++s]=(EDGE){y,fir[x]},fir[x]=s;
edge[++s]=(EDGE){x,fir[y]},fir[y]=s;
}
inline void add(int xl,int xr,int yl,int yr)
{
a[++s]=(line){xl,yl,yr,1};
a[++s]=(line){xr+1,yl,yr,-1};
}
void dfs(int k,int from)
{
dfn[k]=++cnt;
for(int i=fir[k];i;i=edge[i].nex)
if(edge[i].end!=f[k][0])
f[edge[i].end][0]=k,
dfs(edge[i].end,k);
las[k]=cnt;
}
inline int getson(int u,int v)
{
for(int i=16;i>=0;i--)
if(dfn[f[v][i]]>dfn[u])
v=f[v][i];
return v;
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
int n,m,i,j,u,v,son;
long long ans=0;
read(n),read(m);
for(i=1;i<n;i++)
read(u),read(v),inc(u,v);
dfs(1,0);
for(j=1;j<17;j++)
for(i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
for(i=1,s=0;i<=m;i++)
{
read(u),read(v);
if(dfn[u]>dfn[v]) swap(u,v);
if(dfn[u]<dfn[v]&&las[u]>=las[v])
{
son=getson(u,v);
if(dfn[son]>1) add(dfn[v],las[v],1,dfn[son]-1);
if(las[son]<n) add(las[son]+1,n,dfn[v],las[v]);
}
else add(dfn[v],las[v],dfn[u],las[u]);
}
sort(a+1,a+s+1,cmp);
for(i=j=1;i<=n;i++)
{
while(j<=s&&a[j].x==i)
tree.add(1,1,n,a[j].yl,a[j].yr,a[j].num),j++;
ans+=i-1-tree.sum[1];
}
printf("%lld\n",ans);
return 0;
}