Comet OJ - Contest #1
Posted gloid
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Comet OJ - Contest #1相关的知识,希望对你有一定的参考价值。
A:随便怎么暴力。
#include<bits/stdc++.h> using namespace std; #define ll long long #define N 25 char getc(){char c=getchar();while (c!=‘.‘&&c!=‘#‘) 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 T,n,m; char a[N][N]; signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif T=read(); while (T--) { n=read(),m=read(); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) a[i][j]=getc(); int u=0,v=0; for (int i=1;i<=n;i++) { int cnt=0; for (int j=1;j<=m;j++) if (a[i][j]==‘.‘) cnt++; if (cnt>v) u=i,v=cnt; } int l=0,r=0; for (int j=1;j<=m;j++) if (a[u][j]==‘.‘) {l=j;break;} for (int j=m;j>=1;j--) if (a[u][j]==‘.‘) {r=j;break;} cout<<(r-l)/2<<‘ ‘<<u<<‘ ‘<<(l+r)/2<<endl; } return 0; //NOTICE LONG LONG!!!!! }
B:显然选择单字符子串能形成n种不同的串。容易发现其他方案一定是由进位产生的,考虑固定某个9为子串右端点会产生多少种方案。数一下由其往前有多少个连续的9,这一段的每个后缀都会产生一种方案。然后再往前看一个数,若不为0答案再+1;若为0,由于所选串不能有前置0,需要找一下之前有没有非零数,若有则答案+1。
#include<bits/stdc++.h> using namespace std; #define ll long long #define N 200010 char getc(){char c=getchar();while (c!=‘.‘&&c!=‘#‘) 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; } char s[N]; signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif int T=read(); while (T--) { scanf("%s",s+1);int n=strlen(s+1); ll ans=0; bool flag=0;int cnt=0; int first=n+1;for (int i=1;i<=n;i++) if (s[i]!=‘0‘) {first=i;break;} char last=‘0‘; for (int i=1;i<=n;i++) { if (s[i]!=‘9‘) { cnt=0,ans++; last=s[i]; } else { cnt++; ans+=cnt; if (last==‘0‘) ans+=i-cnt>first; else ans++; } } cout<<ans<<endl; } return 0; //NOTICE LONG LONG!!!!! }
C:状态尽量最小表示一下,哈希暴力记搜。
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define N 200010 char getc(){char c=getchar();while (c!=‘.‘&&c!=‘#‘) 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 T,n; struct data { int x,y; bool operator <(const data&a) const { return x>a.x||x==a.x&&y>a.y; } bool operator ==(const data&a) const { return x==a.x&&y==a.y; } }a[22]; map<ull,int> f; ull calc(data *a) { ull s=0; for (int i=0;i<=16;i++) s=s*13+a[i].x,s=s*17+a[i].y; return s; } int work(data *a) { ull h=calc(a); if (f.find(h)!=f.end()) return f[h]; bool flag=0; for (int i=1;i<=16;i++) if (a[i].x==0) break; else { if (i==a[0].x) continue; data b[22]; for (int j=0;j<=16;j++) b[j]=a[j]; a[i].x--;data c=a[i];swap(c.x,c.y);for (int j=1;j<=16;j++) swap(a[j].x,a[j].y);sort(a+1,a+17); for (int j=1;j<=16;j++) if (a[j]==c) {a[0].x=j;break;} int u=work(a); for (int j=0;j<=16;j++) a[j]=b[j]; if (u==-1) return f[h]=1; if (u==0) flag=1; } if (flag) return f[h]=0; else return f[h]=-1; } signed main() { #ifndef ONLINE_JUDGE freopen("d.in","r",stdin); freopen("d.out","w",stdout); #endif T=read();a[0].x=1;f[calc(a)]=0; while (T--) { n=read(); for (int i=1;i<=20;i++) a[i].x=a[i].y=0; for (int i=1;i<=n;i++) a[read()].x++; for (int i=1;i<=n;i++) a[read()].y++; a[0].x=0; sort(a+1,a+21); int x=work(a); if (x==1) puts("AA wins"); if (x==-1) puts("dreamoon wins"); if (x==0) puts("Draw"); } return 0; //NOTICE LONG LONG!!!!! }
D:大讨论大约是可以做的,但大约不是给人写的。考虑简单的做法。套路的将坐标系转45°,使菱形变为正方形,处理出二维前缀和。枚举正方形中心,二分半径,根据该正方形是否包含了所有没有草的点调整二分半径方向。然后判断该正方形中是否没有草,若是则更新答案。于是O(nmlog(n+m))。也可以做到线性,大概没啥本质区别。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 1010 #define mp(x,y) make_pair((x),(y)) char getc(){char c=getchar();while (c!=‘#‘&&c!=‘.‘) 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; } typedef pair<int,int> pii; int T,n,m,a[N<<1][N<<1],s[N<<1][N<<1],s2[N<<1][N<<1]; pii trans(pii a){return mp(a.first+a.second,a.first-a.second+m);} int calc(int x1,int y1,int x2,int y2) { x1=max(x1,1),y1=max(y1,1);x2=min(x2,n+m),y2=min(y2,n+m); return s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]; } int calc2(int x1,int y1,int x2,int y2) { x1=max(x1,1),y1=max(y1,1);x2=min(x2,n+m),y2=min(y2,n+m); return s2[x2][y2]-s2[x1-1][y2]-s2[x2][y1-1]+s2[x1-1][y1-1]; } int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); const char LL[]="%I64d "; #else const char LL[]="%lld "; #endif T=read(); while (T--) { n=read(),m=read(); int cnt=0; for (int i=1;i<=n+m;i++) for (int j=1;j<=n+m;j++) s[i][j]=s2[i][j]=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { char c=getc(); if (c==‘#‘) a[i][j]=0; else a[i][j]=1; cnt+=a[i][j]; s[i+j][i-j+m]=a[i][j];s2[i+j][i-j+m]=1-a[i][j]; } for (int i=1;i<=n+m;i++) for (int j=1;j<=n+m;j++) s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1], s2[i][j]+=s2[i-1][j]+s2[i][j-1]-s2[i-1][j-1]; int ansx=0,ansy=0,ansr=n+m+1; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { int l=0,r=max(n,m),ans=n+m+1; pii t=trans(mp(i,j)); while (l<=r) { int mid=l+r>>1; if (calc(t.first-mid,t.second-mid,t.first+mid,t.second+mid)==cnt) ans=mid,r=mid-1; else l=mid+1; } if (ans!=n+m+1&&calc(t.first-ans,t.second-ans,t.first+ans,t.second+ans)==cnt&&calc2(t.first-ans,t.second-ans,t.first+ans,t.second+ans)==0) if (ans<ansr||ans==ansr&&i<ansx||ans==ansr&&i==ansx&&j<ansy) ansx=i,ansy=j,ansr=ans; } if (ansr==n+m+1) printf("-1 -1 -1 "); else printf("%d %d %d ",ansr,ansx,ansy); } return 0; }
E:对于牛的极长连续段,显然这些牛只能吃与其相邻的草,所以每一段牛互不相干可以分开考虑。对于一段牛,可能吃到的草的数量是牛的数量+1,找到这段里没被吃的草,以该位置将这段牛分成两半,然后只要保证两边的牛都不吃到该草即可。不妨设第一个位置是没被吃的草,容易发现不合法仅当某头向左走的牛移动时,其前方所有牛都已经吃过草。计算概率即可。注意虽然实际上其前方所有向右走的牛都已经吃过草就已经不合法了,但我们只应考虑该牛直接导致不合法的概率。
#include<bits/stdc++.h> using namespace std; #define ll long long #define P 998244353 #define N 200010 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 T,n,inv[N]; char s[N]; signed main() { #ifndef ONLINE_JUDGE freopen("b.in","r",stdin); freopen("b.out","w",stdout); #endif T=read(); inv[0]=inv[1]=1;for (int i=2;i<=100001;i++) inv[i]=P-1ll*(P/i)*inv[P%i]%P; while (T--) { n=2*read()+1;int ans=1; scanf("%s",s+1); int cnt1=0,cnt2=0; for (int i=1;i<=n;i++) { if ((i&1)&&(s[i]==‘.‘)) cnt1++; if (!(i&1)&&(s[i]==‘L‘||s[i]==‘R‘)) ans=1ll*ans*(++cnt2)%P; } if (cnt1!=cnt2) ans=0; else for (int i=2;i<=n;i+=2) if (s[i]==‘L‘||s[i]==‘R‘) { int t=i; while (t+2<=n&&s[t+2]!=‘.‘) t+=2; int cnt=0,pos=0; for (int j=i-1;j<=t+1;j+=2) if (s[j]==‘.‘) cnt++;else pos=j; if (cnt!=(t-i>>1)+1) {ans=0;break;} cnt=0; for (int j=pos-1;j>=i;j-=2) { if (s[j]!=‘L‘) ans=1ll*ans*cnt%P*inv[cnt+1]%P; cnt++; } cnt=0; for (int j=pos+1;j<=t;j+=2) { if (s[j]!=‘R‘) ans=1ll*ans*cnt%P*inv[cnt+1]%P; cnt++; } i=t; } printf("%d ",ans); } return 0; //NOTICE LONG LONG!!!!! }
F:
似乎有小裙子耶
以上是关于Comet OJ - Contest #1的主要内容,如果未能解决你的问题,请参考以下文章