sicnu 区域赛选拔赛
首先是a题,模拟直接求每个点成功的概率
数据规模较小,听说有规律是(n+1)*p
题目链接:https://acm.sicnu.edu.cn/problem/Contest_18_A
#include <bits/stdc++.h> #define INF 1e-8 using namespace std; int main(){ int n,a,b; cin>>n>>a>>b; double maxx=-1; double p=a*1.0/b; int maxk=1; for(int k=0;k<=n;k++){ double s=1.0; for(int i=n;i>=(n-k+1);i--) s*=i*1.0; for(int j=1;j<=k;j++) s/=j*1.0; for(int i=1;i<=k;i++) s*=p; for(int i=1;i<=n-k;i++) s*=(1-p); if(s>maxx||fabs(s-maxx)<=INF){ maxx=s; maxk=k; } //cout<<s<<endl; } cout<<maxk<<endl; return 0; }
b题 ,裸拓扑排序,比赛的时候看都没看,有点难受
题目链接:https://acm.sicnu.edu.cn/problem/Contest_18_B
#include <bits/stdc++.h> using namespace std; int g[105][105]; int dist[105]; int vis[105]; int n,m; void sort_(){ queue<int> num; map<int,int> vis; for(int i=1;i<=n;i++) if(dist[i]==0) {num.push(i);vis[i]++;} int count=0; while(!num.empty()){ int t=num.front(); num.pop(); count++; for(int i=1;i<=n;i++){ if(g[t][i]==1){ g[t][i]=0; dist[i]--; } if(dist[i]==0&&vis[i]==0) {num.push(i);vis[i]++;} } } if(count==n) cout<<"Yes"<<endl; else cout<<"No"<<endl; } int main() { int t,k,a; memset(g,0,sizeof(g)); memset(dist,0,sizeof(dist)); cin>>n>>m; for(int i=0;i<m;i++){ cin>>t>>k; for(int j=0;j<k;j++){ cin>>a; if(g[t][a]==0){ g[t][a]=1; dist[a]++; } } } sort_(); return 0; }
c题,一眼看过去就像***题,但是wa了超级多次,首先是爆int了,没注意,然后是t和s的大小关系,题目中没有明确的确定
题目链接:https://acm.sicnu.edu.cn/problem/Contest_18_C
#include <bits/stdc++.h> using namespace std; struct node{ unsigned long long a,b; long long v; }num[100005]; int cmp(node x,node y){ return x.v<y.v; } int main() { int n,s,t; int x0,y0,z0; int x,y,z; int flag=0; //freopen("e://duipai//data.txt","r",stdin); //freopen("e://duipai//out2.txt","w",stdout); cin>>n>>s>>t; for(int i=0;i<n;i++){ if(i==0) cin>>x0>>y0>>z0; else { cin>>x>>y>>z; num[i].a=(long long)(x-x0)*(x-x0)+(long long)(y-y0)*(y-y0)+(long long)(z-z0)*(z-z0); } } for(int i=0;i<n;i++){ if(i==0) cin>>x0>>y0>>z0; else { cin>>x>>y>>z; num[i].b=(long long)(x-x0)*(x-x0)+(long long)(y-y0)*(y-y0)+(long long)(z-z0)*(z-z0); if(t>s){ if(num[i].a>num[i].b) flag=1; } else { if(num[i].a<num[i].b) flag=1; else swap(num[i].a,num[i].b); } if(flag==0) num[i].v=abs(num[i].b-num[i].a); } } //for(int i=1;i<n;i++) cout<<num[i].a<<" "<<num[i].b<<endl; if(flag==1) cout<<"No"<<endl; else{ sort(num+1,num+n,cmp); for(int i=2;i<n;i++){ if(num[i].a<num[i-1].a) { flag=1; break; } if(num[i].a==num[i-1].a){ if(num[i].v!=num[i-1].v){ flag=1; break; } } } if(flag==1) cout<<"No"<<endl; else cout<<"Yes"<<endl; } return 0; }
d题,拿到题目理解错题意以为这个数字的组成可以是无序的,然后找dp状态数太多了,根本无法优化,比赛的时候就放了
然后比赛后,队友告诉我,这个数字是有序的,直接暴力就行了,难受到爆炸
题目链接:https://acm.sicnu.edu.cn/problem/Contest_18_D
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int main() { int n,m=0; int num[100]; int s[100]; string s1; cin>>n; cin>>s1; for(int i=0;i<n;i++) s[i]=s1[i]-'0'; for(int i=0;i<n;i++) m+=s[i]; int len=0; for(int i=2;i<=n;i++){ if(m%i==0) num[len++]=i; } for(int i=0;i<len;i++){ int ans=m/num[i]; int flag=num[i]; for(int j=0;j<n;j++){ if(ans>s[j]) ans-=s[j]; else if(ans==s[j]) {ans=m/num[i];flag--;} else {flag=1;break;} } if(flag==0){ cout<<"Yes"<<endl; return 0; } } cout<<"No"<<endl; return 0; }
最后一题是最坑的,无限循环小数转分数,一开始的思路是枚举分母,与这个小数相乘,大概估算分子,然后比赛过程中一直wa,可能是枚举的时候数据开小了
比赛完,说是规律题,瞬间炸了,然后推了推,发现确实挺好发现的规律,然后在网上也找到了,证明的方法https://blog.csdn.net/weixin_35653315/article/details/72190641
附上代码吧
#include <bits/stdc++.h> #define INF 1e-6 using namespace std; long long gcd(long long a,long long b){ return b==0?a:gcd(b,a%b); } int main(){ long long n=0,m=0,sw=0; long long len=1; string s; cin>>s; int vis=0; for(int i=2;i<s.length();i++){ if(s[i]=='(') vis=1; if(vis==0){ n*=10; n+=s[i]-'0'; len*=10; sw*=10; sw+=s[i]-'0'; } else { if(s[i]!='('&&s[i]!=')'){ m*=10; m+=9; n*=10; n+=s[i]-'0'; } } } n-=sw; m*=len; long long t=gcd(n,m); cout<<n/t<<"/"<<m/t<<endl; return 0; }