2019.08.07【NOIP提高组】模拟 A 组 比赛总结

题目

【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

在这里插入图片描述

扫描二维码关注公众号,回复: 11879425 查看本文章

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+2fn,结果推了不到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,f2fk分别乘多少得到。
然后就可以矩阵乘法了。

T2

其实这题是最简单的,甚至不用二分图最大匹配,一个贪心即可AC。
可以把转折点从小到大排序,梦境区间按左端点从小到大的顺序排序,然后处理转折点。
如果一个梦境区间的左端点小于等于当前转折点,那么我们把它放入一个按右端点从小到大排序的里面。
接下来每次取出堆顶判断一下就可以了。

T3

先把每一个点求dfs序,这样相同子树的点的编号是连续的,处理就方便得多了。
接下来对于每一个询问(u,v)分类讨论:

  1. 如果u和v在同一条链内,假定u为祖先,那么u的其他子树和子树u以外的所有点都不能与v形成点对;
  2. 否则,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(n1)减去即是答案。


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;
}

猜你喜欢

转载自blog.csdn.net/huangzihaoal/article/details/98885771
今日推荐