NOIP2017賽前模擬10月30日總結
阿新 • • 發佈:2017-10-30
span 進行 [1] code amp sin 簡單 tdi line
題目1:
n個人參賽(n<=100000),每個人有一個權值··已知兩個人權值絕對值之差小於等於K時,兩個人都有可能贏,若大於則權值大的人贏···比賽為淘汰制,進行n-1輪·問最後可能贏的人有多少個?
考點:簡單分析
直接將權值排序,從大到小掃一遍直到num[i+1]-num[i]>k停止··此時答案等於n-i
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<string> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+5; inline int R() { char c;int f=0; for(c=getchar();c<‘0‘||c>‘9‘;c=getchar()); for(;c<=‘9‘&&c>=‘0‘;c=getchar()) f=(f<<3)+(f<<1)+c-‘0‘; return f; } int n,k,T,num[N]; int main() { T=R(); while(T--) { n=R(),k=R(); for(int i=1;i<=n;i++) num[i]=R(); sort(num+1,num+n+1); int ans=1; for(int i=n-1;i>=1;i--) { if(num[i+1]-num[i]<=k) ans++;else break; } cout<<ans<<"\n"; } return 0; }
題目2:
有n個數從左到右排列··豆豆和豆沙從左到右交替取,豆豆第一次可以取1個或2個數,之後若前一個人拿了K個數··則後面的人只能拿K或K+1個數··n<=20000,若每次兩人拿的時候都采用最優策略,那麽豆豆會比豆沙多拿總和多大的數?
考點:dp
和第一次NOIP總結中的T2很像··我們用f[i][j]表示先手從i開始拿j個之後能最多比後手多拿多大,得出轉移方程:
f[i][j]=sum[i+j-1]-sum[i-1]-max(f[i+j][j],f[i+j][j+1]);
sum為數的前綴和,最後比較f[1][1]和f[1][2]即可,由於j每次枚舉最大不會超過根號n,復雜度為n^3/2;
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<string> #include<cstring> #include<algorithm> using namespace std; const int N=2e4+5; int T,n,f[N][205],num[N],sum[N]; inline int R(){ char c;int f=0,i=1; for(c=getchar();(c<‘0‘||c>‘9‘)&&c!=‘-‘;c=getchar()); if(c==‘-‘) i=-1,c=getchar(); for(;c<=‘9‘&&c>=‘0‘;c=getchar()) f=(f<<3)+(f<<1)+c-‘0‘; return f*i; } int main() { T=R(); while(T--){ memset(sum,0,sizeof(sum));memset(f,0,sizeof(f)); n=R(); for(int i=1;i<=n;i++) sum[i]=num[i]=R(),sum[i]+=sum[i-1]; for(int i=n;i>=1;i--) for(int j=1;i+j-1<=n&&j<=200&&j<=i+1;j++) f[i][j]=sum[i+j-1]-sum[i-1]-max(f[i+j][j],f[i+j][j+1]); cout<<max(f[1][2],f[1][1])<<endl; } return 0; }
題目3:
給定一個無向圖,問圖中共邊三元環有多少對,點數n<=100000,m<=200000;
考點:圖論
很妙的一道題···我們枚舉每一個點u··然後找到與該點相連且度數比該點小的點v··然後找既與v相連由於u相連的點的數量計算對答案貢獻即可··復雜度為m^3/2次方
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> #include<vector> using namespace std; const int M=2e5+5; const int N=1e5+5; vector<int>ed[N]; inline int R(){ char c;int f=0; for(c=getchar();c<‘0‘||c>‘9‘;c=getchar()); for(;c<=‘9‘&&c>=‘0‘;c=getchar()) f=(f<<3)+(f<<1)+c-‘0‘; return f; } int T,n,m,du[N],tag[N],tim; long long ans=0; inline void pre(){ for(int i=1;i<=n;i++) ed[i].clear(); memset(du,0,sizeof(du));tim=0;ans=0; memset(tag,0,sizeof(tag)); } inline void getans(){ for(int i=1;i<=n;i++){ tim++; for(int j=0;j<ed[i].size();j++) { int v=ed[i][j];tag[v]=tim; } for(int j=0;j<ed[i].size();j++){ int v=ed[i][j]; if(du[v]<du[i]||(du[v]==du[i]&&v<i)){ int cnt=0; for(int k=0;k<ed[v].size();k++) if(tag[ed[v][k]]==tim) cnt++; ans+=(long long)cnt*(cnt-1)/2; } } } } int main() { T=R(); while(T--){ n=R(),m=R();pre();int a,b; for(int i=1;i<=m;i++) a=R(),b=R(),du[a]++,du[b]++,ed[a].push_back(b),ed[b].push_back(a); getans();cout<<ans<<endl; } }
NOIP2017賽前模擬10月30日總結