正睿初阶
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;
}