牛客OI測試賽2
阿新 • • 發佈:2020-08-23
A.無序組數
暴力求出A和B的因子,注意二元組是無序的,因此還要考慮有些因子在A和B中都存在的情況
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int maxn=100006; int a[maxn],ans[maxn]; int vis[maxn]; int main(){ int t; scanf("%d",&t); while(t--){ int m,n; scanf("%d%d",&m,&n); for(int i=1;i<=max(m,n);i++) vis[i]=0; int x=m,y=n,cnt=0,sum1=0,sum2=0; for(int i=1;i<=m;i++){ if(m%i==0&&vis[i]==0){ sum1++; vis[i]=1; } } for(int i=1;i<=n;i++){ if(n%i==0){ sum2++; if(vis[i]==1) cnt++; } } printf("%d\n",sum1*sum2-(cnt-1)*cnt/2); } }
B.路徑數量
$dp[v][i]$表示從1號點到$v$號點長度為i的路徑數目,則$dp[v][i]=dp[v][i]+dp[j][
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<stack> #include<vector> using namespace std; typedef long long ll; const int maxn=36; vector<int> g[maxn]; ll dp[maxn][maxn]; int main(){ int n,k; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ int z; scanf("%d",&z); if(z==1){ g[i].push_back(j); if(i==1) dp[j][1]=1; } } for(int i=1;i<=k;i++) for(int j=1;j<=n;j++) for(int z=0;z<g[j].size();z++) { int v=g[j][z]; dp[v][i]=dp[v][i]+dp[j][i-1]; } cout<<dp[n][k]<<endl; }
C.數列下標
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int maxn=100006; int a[maxn],ans[maxn]; int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ if(a[j]>a[i]){ ans[i]=j; break; } } } for(int i=1;i<n;i++) printf("%d ",ans[i]); printf("%d\n",ans[n]); }
D.星光晚餐
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int maxn=100006; int a[maxn],ans[maxn]; int vis[maxn]; int main(){ long long n; cin>>n; cout<<(long long )sqrt(n)<<endl; }
E.括號序列
和括號匹配想法一樣,每次遇到左括號sum++,遇到右括號如果sum為零,說明需要交換,使sum++,ans++,如果sum為正,則sum--
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<stack> using namespace std; const int maxn=10000006; int a[maxn],ans[maxn]; int vis[maxn]; char s[maxn]; int main(){ int n; int sum=0; int ans=0; scanf("%d",&n); scanf("%s",s+1); //cout<<s+1<<endl; for(int i=1;i<=n;i++) if(s[i]=='(') sum++; else if(s[i]==')'){ if(sum>0) sum--; else if(sum<=0){ sum++; ans++; } } cout<<ans<<endl; }
根據斯特林公式:$n!\approx\sqrt{2\pi n}{(\frac{n}{e})}^n$,兩邊同時取對數,再對$n$進行二分即可
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<stack> #include<vector> using namespace std; typedef long long ll; const int maxn=36; vector<int> g[maxn]; ll dp[maxn][maxn]; int main(){ ll l=0,r=1e12,mid; ll x; scanf("%lld",&x); for(int i=1;i<1000;i++){ mid=(l+r)/2.0; if(log(sqrt(2*acos(-1)*mid))+mid*log(mid/exp(1.0))<x*log(x)) l=mid; else r=mid; } cout<<r<<endl; }