A:签到。没仔细看数据范围,看到一个O(nt)的差点叉上去了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 110
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,a[N],b[N];
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read(),m=read();
int ans=1000000,ansi=0;
for (int i=1;i<=n;i++)
{
a[i]=read(),b[i]=read();
if (a[i]<m) a[i]+=b[i]*((m-a[i]-1)/b[i]+1);
if (a[i]<ans) ans=a[i],ansi=i;
}
cout<<ansi;
return 0;
//NOTICE LONG LONG!!!!!
}
B:从大到小考虑每个数,放在所有能放但还没有放的位置上即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 110
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,h,a[N],b[N],c[N][N],d[N][N];
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read(),m=read(),h=read();
for (int i=1;i<=m;i++) b[i]=read();
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
c[i][j]=read();
for (int i=h;i>=1;i--)
for (int x=1;x<=n;x++)
for (int y=1;y<=m;y++)
if (c[x][y]&&i<=a[x]&&i<=b[y]&&!d[x][y]) d[x][y]=i;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
cout<<d[i][j]<<' ';
cout<<endl;
}
return 0;
//NOTICE LONG LONG!!!!!
}
C:在右括号够的情况下尽量放左括号。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 300010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,c[N][2];char s[N];
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
scanf("%s",s+1);
for (int i=n;i>=1;i--)
{
c[i][0]=c[i+1][0],c[i][1]=c[i+1][1];
if (s[i]=='(') c[i][0]++;
if (s[i]==')') c[i][1]++;
}
int cnt=0;
for (int i=1;i<=n;i++)
{
if (s[i]=='(') cnt++;
else if (s[i]==')') cnt--;
else
{
if (n-i-c[i][0]<cnt+c[i][0]+1) s[i]=')',cnt--;
else s[i]='(',cnt++;
}
if (cnt<0||cnt==0&&i<n) goto err;
}
if (cnt>0) goto err;
printf("%s",s+1);
return 0;
err:cout<<":(";
//NOTICE LONG LONG!!!!!
}
D:这种东西容易想到二分答案,转化成01问题后,设f[i]为要让i号点为1其子树内至少有几个叶子为1,转移显然。dp完之后可以发现压根不需要二分答案。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 300010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,a[N],b[N],p[N],f[N],fa[N],t,leaves;
struct data{int to,nxt;
}edge[N];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void dfs(int k)
{
for (int i=p[k];i;i=edge[i].nxt)
dfs(edge[i].to);
if (!p[k]) leaves++,f[k]=1;
else
if (a[k])
{
f[k]=N;
for (int i=p[k];i;i=edge[i].nxt)
f[k]=min(f[k],f[edge[i].to]);
}
else
{
f[k]=0;
for (int i=p[k];i;i=edge[i].nxt)
f[k]+=f[edge[i].to];
}
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
for (int i=1;i<=n;i++) a[i]=read();
for (int i=2;i<=n;i++)
{
fa[i]=read();
addedge(fa[i],i);
}
dfs(1);
cout<<leaves-f[1]+1;
return 0;
err:cout<<":(";
//NOTICE LONG LONG!!!!!
}
E:询问每一行,考虑其答案的奇偶性,若有奇数,一定有两行均为奇数,头和尾就在这两行内;若没有奇数,说明头和尾在同一行,再询问每一列找到在哪两列即可。确定行/列后直接二分即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 1010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n;
signed main()
{
n=read();
int x=0,y=0;
for (int i=1;i<=n;i++)
{
if (x==0&&i==n) break;
cout<<'?'<<' '<<i<<' '<<1<<' '<<i<<' '<<n<<endl;
int u=read();
if (u&1) if (x) y=i;else x=i;
}
if (!x)
{
int ansx[3],ansy[3],cnt=0;
for (int i=1;i<=n;i++)
{
cout<<'?'<<' '<<1<<' '<<i<<' '<<n<<' '<<i<<endl;
int u=read();
if (u&1)
{
int l=1,r=n;
while (l<r)
{
int mid=l+r>>1;
cout<<"?"<<' '<<l<<' '<<i<<' '<<mid<<' '<<i<<endl;
int u=read();
if (u&1) r=mid;
else l=mid+1;
}
cnt++;ansx[cnt]=l,ansy[cnt]=i;
}
}
cout<<"!";
for (int i=1;i<=cnt;i++) cout<<' '<<ansx[i]<<' '<<ansy[i];
}
else
{
int ansx[3],ansy[3],cnt=0;
int i=x;
int l=1,r=n;
while (l<r)
{
int mid=l+r>>1;
cout<<"?"<<' '<<i<<' '<<l<<' '<<i<<' '<<mid<<endl;
int u=read();
if (u&1) r=mid;
else l=mid+1;
}
cnt++;ansx[cnt]=i,ansy[cnt]=l;
i=y;
l=1,r=n;
while (l<r)
{
int mid=l+r>>1;
cout<<"?"<<' '<<i<<' '<<l<<' '<<i<<' '<<mid<<endl;
int u=read();
if (u&1) r=mid;
else l=mid+1;
}
cnt++;ansx[cnt]=i,ansy[cnt]=l;
cout<<"!";
for (int i=1;i<=cnt;i++) cout<<' '<<ansx[i]<<' '<<ansy[i];
}
return 0;
//NOTICE LONG LONG!!!!!
}
F:不妨设总长度为1,最后再乘l即可。考虑坐标为i的点的贡献,其被k条线段覆盖的概率是C(n,k)pn-k(1-p)k,其中p=i2+(1-i)2=2i2-2i+1。对每个k暴力积分即可,直接暴力进行多项式运算。可能略卡常。场上居然以为积分求逆元要带log,自闭了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 2010
#define P 998244353
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,k,l,ans,C[N][N],f[N<<1],h[N<<1],Inv[N<<1],g[N];
int ksm(int a,int k)
{
int s=1;
for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
return s;
}
int inv(int a){return ksm(a,P-2);}
void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
void mul(int m,int *f,int *g,int n)
{
memset(h,0,sizeof(h));
for (int i=0;i<=m;i++)
for (int j=0;j<min(i+1,n);j++)
inc(h[i],1ll*f[i-j]*g[j]%P);
for (int i=0;i<=m;i++) f[i]=h[i];
}
void div(int m,int *f,int *g,int n)
{
h[2]=f[m],h[1]=f[m-1];f[m]=f[m-1]=0;
int x=inv(g[2]);
for (int i=m-2;i>=0;i--)
{
h[0]=f[i];
f[i]=1ll*h[2]*x%P;
h[2]=(h[1]+P-1ll*g[1]*f[i]%P)%P;
h[1]=(h[0]+P-1ll*g[0]*f[i]%P)%P;
}
}
int calc()
{
int s=0;
for (int i=1;i<=n*2+1;i++) inc(s,1ll*f[i-1]*Inv[i]%P);
return s;
}
signed main()
{
n=read(),k=read(),l=read();
C[0][0]=1;
for (int i=1;i<=n;i++)
{
C[i][0]=1;
for (int j=1;j<=i;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%P;
}
Inv[0]=Inv[1]=1;for (int i=2;i<=n*2+4;i++) Inv[i]=P-1ll*(P/i)*Inv[P%i]%P;
f[0]=1;
g[0]=0,g[1]=2,g[2]=P-2;
for (int i=1;i<=k;i++) mul(i*2,f,g,3);
g[0]=1,g[1]=P-2,g[2]=2;
for (int i=1;i<=n-k;i++) mul((i+k)*2,f,g,3);
inc(ans,1ll*C[n][k]*calc()%P);
for (int i=k+1;i<=n;i++)
{
g[0]=1,g[1]=P-2,g[2]=2;
div(n*2,f,g,3);
g[0]=0,g[1]=2,g[2]=P-2;
mul(n*2,f,g,3);
inc(ans,1ll*C[n][i]*calc()%P);
}
ans=1ll*ans*l%P;
cout<<ans;
return 0;
//NOTICE LONG LONG!!!!!
}
小小号打的。result:rank 27 rating +222