1. 程式人生 > >NOIP2017賽前模擬10月30日總結

NOIP2017賽前模擬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日總結