noip模拟3
这场好难。
A 网格
队列里的结构体数组开大了导致 RE。。。
正解很简洁,对于现在有的字符串,添加一个数字或符号的转移是相对固定的:
添加一个数字,如果前一位是运算符,那么久新加一个数字,否则,让现在的数字乘以 10 加上它;
添加运算符同理。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e3+1,mod=998244353;
int n,m;
char s[N][N];
int dp1[N][N],dp2[N][N],dp3[N][N],dp4[N][N];
signed main()
{
freopen("grid.in","r",stdin);
freopen("grid.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
dp2[1][0]=1,dp4[1][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
dp4[i][j]=(dp4[i-1][j]+dp4[i][j-1])%mod,dp1[i][j]=(dp1[i-1][j]+dp1[i][j-1])%mod;
dp2[i][j]=(dp2[i-1][j]+dp2[i][j-1])%mod,dp3[i][j]=(dp3[i-1][j]+dp3[i][j-1])%mod;
if(s[i][j]=='+')dp1[i][j]=(dp1[i][j]+dp3[i][j])%mod,dp2[i][j]=dp4[i][j],dp3[i][j]=0;
else if(s[i][j]=='*') dp2[i][j]=dp3[i][j],dp3[i][j]=0;
else dp3[i][j]=(dp3[i][j]*10+(s[i][j]-'0')*dp2[i][j])%mod;
}
}
printf("%lld",(dp1[n][m]+dp3[n][m])%mod);
return 0;
}
B 矩形
太可惜了,考场上写出来 \(O(n^2 \log n)\) 做法但是 RE,敲的不对。
写对了有 \(64\) 分。
正解和我的思路很相似,但是存的东西不同。要存点的相对位置,看有多少组点可以上下匹配,然后再乘上系数。
需要离散化。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
const int M=500;
#define ll long long
#define ull unsigned long long
int n;
ll ans;
struct nd{
int x,y,id;
bool operator<(const nd &t){
if(x!=t.x)return x<t.x;
return y<t.y;
}
}a[N];
vector<int> ve[N];
int siz[N];
int mxx,mnx=1e9,mxy,mny=1e9;
int id[N],cnt,B;
ull sta[N],tp;
ull t=998244353;
ull hashp(int x,int y){
return t*x+y;
}
const ll SZ=1.8e6+3;
ll gx(int x,int y){
int l=0,r=0;
ll res=0;
for(;r<siz[y];r++){
while(ve[x][l]<ve[y][r]&&l<siz[x]-1)l++;
if(ve[x][l]==ve[y][r])res++;
}
return res*(res-1)/2;
}
struct hash_map{
struct data {
ull u;
int v,nex;
}e[SZ<<1];
int h[SZ],cnt;
int hash(ull u){return u%SZ;}
int &operator[](ull u) {
ll hu = hash(u);
for (int i=h[hu];i;i=e[i].nex){
if(e[i].u==u)return e[i].v;
}
return e[++cnt]=data{u,0,h[hu]},h[hu]=cnt,e[cnt].v;
}
void clear(){
cnt=0;
memset(h,0,sizeof(h));
}
}mp;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
#ifndef LOCAL
freopen("rect.in","r",stdin);
freopen("rect.out","w",stdout);
#endif
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
a[i].id=i;
}
sort(a+1,a+n+1);
int tmp=500;
B=max(1,tmp);
for(int i=1;i<=n;i++){
if(a[i].x!=a[i-1].x){
cnt++;
}
id[i]=cnt;
ve[cnt].push_back(a[i].y);
}
for(int i=1;i<=cnt;i++){
siz[i]=ve[i].size();
}
for(int i=1;i<=cnt;i++){
if(siz[i]<=B){
for(int j=0;j<siz[i];j++){
for(int k=j+1;k<siz[i];k++){
ull nowh=hashp(ve[i][j],ve[i][k]);
ll val=mp[nowh];
ans+=val;
sta[++tp]=nowh;
}
}
while(tp)mp[sta[tp--]]++;
}
else{
for(int j=1;j<=cnt;j++){
if((siz[j]>B&&j<i)||j==i)continue;
ans+=gx(i,j);
}
}
}
cout<<ans;
return 0;
}
C 集合
不可做。
D 倒水
\(52\) 分的 dp+性质:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
const int N=1e5+4;
int a[N],p[N];
int calc[N];
int cnt=0;
const int mod=998244353;
int ppow(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=(res*a)%mod;
a=(a*a)%mod,b>>=1;
}return res;
}
void dfs(int x)
{
if(x==n+1)
{
++cnt;cnt%=mod;
for(int i=1;i<=n;i++) calc[i]+=p[i];
return ;
}
for(int i=1;i<=n;i++)
{
if(i==x) continue;
int tmp=min(a[i]-p[i],p[x]);
p[i]+=tmp,p[x]-=tmp;
dfs(x+1);
p[i]-=tmp,p[x]+=tmp;
}
}
int q[N];
int ans[N],dp[401][401];
signed main()
{
freopen("bottle.in","r",stdin);
freopen("bottle.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;
bool _=1;
for(int i=1;i<=n;i++) cin>>a[i],_&=(a[i]==1);
if(_)
{
int inv=ppow(n-1,mod-2);
int pos=1;
p[1]=1;
for(int i=2;i<=n;i++)
{
p[i]=pos*inv%mod,pos=(pos+p[i])%mod;
}
pos=p[n],q[n]=0;
for(int i=n-1;i>=1;i--)
{
q[i]=pos*inv%mod,pos=(pos+p[i])%mod;
}
for(int i=1;i<=n;i++) cout<<q[i]<<"\n";
return 0;
}
if(n<=8)
{
p[1]=a[1];
dfs(1);
const int inv=ppow(cnt,mod-2);
for(int i=1;i<=n;i++) calc[i]=(calc[i]*inv)%mod,cout<<calc[i]<<"\n";
return 0;
}
int inv=ppow(n-1,mod-2);
dp[1][a[1]]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=a[i];j++)
{
int p=inv*dp[i][j]%mod;
for(int k=1;k<i;k++)
{
int v=min(j,a[k]);
ans[i]+=p*(j-v),ans[i]%=mod;
ans[k]+=p*v,ans[k]%=mod;
}
for(int k=i+1;k<=n;k++)
{
int v=min(j,a[k]);
ans[i]+=p*(j-v),ans[i]%=mod;
dp[k][v]+=inv*dp[i][j],dp[k][v]%=mod;
}
}
}
for(int i=1;i<=n;i++) cout<<ans[i]<<"\n";
return 0;
}