正睿初阶

22noip10连 day10

水仙花

考虑正难则反,把 两个至少满足一个 变为 两个都不满足
我们发现反着想有一条十分优美的性质,那就是最长的不合法序列是 \(O(\log m)\) 级别的。那么意味着预处理 \(s_i\) (长度为 \(i\) 的不合法序列的方案数)的时间复杂度是 \(O(m \log^2m)\)
然后容斥,数列中的数可重复

#include<bits/stdc++.h>
using namespace std; 
const int N=1e5+10,p=998244353;
int n,m,s[20],f[N],g[20][N];
int main()
{
    cin>>n>>m;s[1]=m;
    for(int i=1;i<=m;i++)g[1][i]=1;
    for(int i=2;i<=17;i++)
        for(int j=1;j<=m;j++){
            for(int k=2*j;k<=m;k+=j)g[i][k]=(g[i][k]+g[i-1][j])%p;
            s[i]=(s[i]+g[i][j])%p;
        }
    f[0]=1;
    for(int i=0;i<n;i++)
        for(int j=1;j<=min(n-i,17);j++)
            f[i+j]=(f[i+j]+1ll*(j&1?1:-1)*f[i]*s[j]%p)%p;
    cout<<(f[n]+p)%p;
    return 0;
}

22noip10连 day9

激光

通过排序确定上下或者左右关系,重新开一个数组记录这个关系,查找是否有空位的手法简洁

#include<bits/stdc++.h>
#define N 200005
using namespace std;
int T,n,m,k,b[N][4];
char s[5];
struct node{int x,y,tp,id;}a[N];
bool cmp1(const node &p,const node &q){return p.x<q.x||p.x==q.x&&p.y<q.y;}
bool cmp2(const node &p,const node &q){return p.y<q.y||p.y==q.y&&p.x<q.x;}
bool cmp3(const node &p,const node &q){return p.id<q.id;}
void solve(){
	stable_sort(a+1,a+k+1,cmp1);
	for(int i=1;i<k;i++)if(a[i].x==a[i+1].x){
		if(a[i].tp==1)b[a[i+1].id][0]=0;
		if(a[i+1].tp==0)b[a[i].id][1]=0;
	}
	stable_sort(a+1,a+k+1,cmp2);
	for(int i=1;i<k;i++)if(a[i].y==a[i+1].y){
		if(a[i].tp==3)b[a[i+1].id][2]=0;
		if(a[i+1].tp==2)b[a[i].id][3]=0;
	}
	stable_sort(a+1,a+k+1,cmp3);
	int cnt=0,ff=0;
	for(int i=1;i<=k;i++)if(!b[i][a[i].tp]){
		if((++cnt)>=3){puts("No");return;}
		int flag=0;
		for(int t=0;t<4;t++)flag|=b[i][t];
		ff|=flag;
	}
	if(ff||!cnt)puts("Yes");
	else puts("No");
}
int main(){
	cin>>T;
	while(T--){
		scanf("%d%d%d",&n,&m,&k);
		for(int i=1;i<=k;i++){
			scanf("%d%d%s",&a[i].x,&a[i].y,s),a[i].id=i;
			if(s[0]=='L')a[i].tp=0;
			if(s[0]=='R')a[i].tp=1;
			if(s[0]=='U')a[i].tp=2;
			if(s[0]=='D')a[i].tp=3;
			for(int t=0;t<4;t++)b[i][t]=1;
		}
		solve();
	}
	return 0;
}

noip十连测day8

模板题

详看注释,这个目测

#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef unsigned long long u64;
const int p=1145141999;
int a[10000005],b[10000005],s[10000005];
int n,m,q,w;
u64 seed;
u64 rnd()
{
	u64 x = seed;
	x ^= x << 13;
	x ^= x >> 7;
	x ^= x << 17;
	return seed = x;
}
int query(int x)
{	
	int ans=0;
	for(int i=0;i<=min(n,x);i++)
	{
		ans=(ans+a[i]*s[min(x-i,m)]%p)%p;
	}
	/*
	a1,a2,a3,a4
	b1,b2,b3,b4,b5
	x1:a1+b1
	x2:a2+a1*b1+b2
	x3:a3+a2*b1+a1*b2+b3
	x4:a4+a3*b1+a2*b2+a1*b3+b4
	x5:a3*b2+a2*b3+a1*b4+b5
	x6:a4*b2+a3*b3+a2*b4+a1*b5
	x7:a4*b3+a3*b4+a2*b5
	x8:a4*b4+a3*b5
	x9:a4*b5
	这里漏了x0,不过同理 
	假设x=5
	a[1]*s[4]+ ····
	这个算式应该是现场打表看出来的 
	*/
	return (ans+p)%p;
}
signed main(){
	scanf("%lld%lld%llu%lld",&n,&m,&seed,&w);
	scanf("%lld",&q);
	for(int i=0;i<=n;++i)a[i]=rnd()%w;
	for(int i=0;i<=m;++i)b[i]=rnd()%w;
	s[0]=b[0];
	for(int i=1;i<=m;i++)
	{
		s[i]=(s[i-1]+b[i])%p;
	}
	int l,r;
	for(int i=1;i<=q;++i)
	{
		scanf("%lld%lld",&l,&r);
		printf("%lld\n",(query(r)-(l?query(l-1):0)+p)%p);	
	}
	return 0;
}
posted @ 2023-02-26 21:17  zyc_xianyu  阅读(31)  评论(0编辑  收藏  举报