グループの問題解決を改善NOIP2014

\(D1T1 \) じゃんけんのビッグバンのバージョン \((OK)\)

\(D1T2 \) 関節の重み \((OK)\)

\(D1T3 \) 飛ぶ鳥 \((OK)\)

\(D2T1 \) 無線ネットワーク送信機位置 \((OK)\)

\(D2T2 \) あなたの方法を見つけること \((OK)\)

\(D2T3 \) 方程式の解 \((OK)\)

今年は、暫定的に終了Sahuaと考え、対象はまだ比較的単純であり、おそらく任意の高度なアルゴリズムとデータ構造吐き気のタイトルバーではありません。

\(D1T1 \)直接ケースのスコアを保存することができる二次元アレイを開きます。次に、2つのパンチが追加される\は(N \) 次いでシミュレーションを議論することができます。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=1005;
int n,na,nb,ans1,ans2;
int a[N],b[N],c[5][5];
int main(){
    n=read();na=read();nb=read();
    for(int i=1;i<=na;++i)a[i]=read();
    for(int i=1;i<=nb;++i)b[i]=read();
    c[0][1]=c[0][4]=0;c[0][2]=c[0][3]=1;
    c[1][2]=c[1][4]=0;c[1][0]=c[1][3]=1;
    c[2][0]=c[2][3]=0;c[2][1]=c[2][4]=1;
    c[3][0]=c[3][1]=0;c[3][2]=c[3][4]=1;
    c[4][2]=c[4][3]=0;c[4][0]=c[4][1]=1;
    for(int i=1;i<=na;++i){
        for(int j=1;i+j*na<=n;++j)a[i+na*j]=a[i];
    }
    for(int i=1;i<=nb;++i){
        for(int j=1;i+j*nb<=n;++j)b[i+nb*j]=b[i];
    }
    for(int i=1;i<=n;++i){
        ans1+=c[a[i]][b[i]];
        ans2+=c[b[i]][a[i]];
    }
    printf("%d %d\n",ans1,ans2);
    return 0;
}

\(D1T2 \)最近行わ。ツリーやすいの点2から同じノードに接続された2つのノードが、我々はすべての点の条件を満たして見つけるために、このような「ノード」を列挙することを考えます右。

ノードuの2つだけのノードV_1は、V_2がそれに接続されている場合まず、特別な状況を考慮して、このノードによって生成された寄与である\(W [V_1] * W [V_2] + W [V_2] * W [V_1] \) すなわち、(ポイントが順序付けされ、それは二回寄与を生成することに注意してください)(2 * W [V_1] * W [V_2] \)\即ち(\(W [V_1] + W [V_2])^ 2- Wは、[V_1] ^ W-2 [V_2] ^ 2 \) のみ3つのノードuがノード場合(V_1、V_2、v_3 \ \ ) 、ノードの寄与が生成され、それに接続されている\(2 * W [ V_1] * W [V_2] + 2 * W [V_1] * W [V_3] + 2 * W [V_2] * W [V_3] \) = \((W [V_1] + W [V_2] + W [V_3 ])^ 2-W [V_1 ] ^ 2-W [V_2] ^ 2-W [v_3] ^ 2 \)

我々はノードと結論付けることができ、これらの2つの特殊なケースによって\(U \)と、\(K \)は、それに接続されたノード、ノード\(U \)の寄与が生成される\((\ sum_ { I = 1} ^ K(W [V_I]))^ 2- \ sum_ {i = 1} ^ KW [V_I] ^ 2 \)

その後、我々は、直接\(O(n)を\)各ノードを介して、それに接続されたすべてのノードを横切る限り、最大合計重量接続されたノードを通過する際、ノードの2最大値を見つけるための権利を得るようにするため、および関節の第1の部分は、2つの前部と後部とに分割され、上記の式に従って右に値について、減算統計への最終的な答えを算出します。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int mod=10007;
const int N=2e5+5;
int ans1,ans2,val[N];
int tot,head[N],nxt[N<<1],to[N<<1];
inline void add(int a,int b){nxt[++tot]=head[a];head[a]=tot;to[tot]=b;}
int main(){
    int n=read();
    for(int i=1;i<n;++i){
        int a=read(),b=read();
        add(a,b);add(b,a);
    }
    for(int i=1;i<=n;++i)val[i]=read();
    for(int u=1;u<=n;++u){
        int max1=0,max2=0;ll tot1=0,tot2=0;
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i];
            if(val[v]>max1)max2=max1,max1=val[v];
            else if(val[v]>max2)max2=val[v];
            tot1=(tot1+val[v])%mod;tot2=(tot2+val[v]*val[v]%mod)%mod;
        }
        ans1=max(ans1,max1*max2);
        ans2=(ans2+tot1*tot1%mod-tot2+mod)%mod;
    }
    printf("%d %d\n",ans1,ans2);
    return 0;
}

\(D1T3 \)最近行われ、書かれたブログ

\(D2T1 \)は、ジャストインタイムの複雑さ、そして暴力統計は公共の場所に設置することができ、二次元プレフィックスとも、各交差点を列挙するために、直接暴力のデータ範囲を見ては、各交差点でカバレッジを得ることができるものについて考え始めた\( O(128 ^。4)\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
int w[200][200];
int main(){
    int d=read(),n=read();
    for(int i=1;i<=n;++i){
        int x=read(),y=read(),z=read();
        ++x;++y;w[x][y]+=z;
    }
    int ans1=0,ans2=0;
    for(int i=1;i<=129;++i){
        for(int j=1;j<=129;++j){//枚举路口,如果你从什么i+d,j+d开始枚举,就会获得70分的好成绩
            int cnt=0;
            for(int k=max(1,i-d);k<=min(i+d,129);++k)
                for(int l=max(1,j-d);l<=min(j+d,129);++l)cnt+=w[k][l];
            if(cnt==ans1)++ans2;
            if(cnt>ans1)ans1=cnt,ans2=1;
        }
    }
    printf("%d %d\n",ans2,ans1);
    return 0;
}

\(D2T2 \)第二のサンプルを再生するには、手を見つけることができます:の程度から抗マップの構築、\(0 \)は、ビューの非エンドポイントである、トポロジカルソートの実行を、数値が点マークによってマークされていますこれらの点は、あなたがタグを逆最短図で実行を開始するために端から継続して後に。行くことができない、直接または間接的に最後に接続していない正の図です。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=10005;
const int M=200005;
int n,m,s,t,deg[N],visit[N],bj[N],dis[N];
queue<int>q;vector<int>g[N];
int main(){
    n=read();m=read();
    for(int i=1;i<=m;++i){
        int a=read(),b=read();
        if(a==b)continue;
        g[b].push_back(a);++deg[a];
    }
    for(int i=1;i<=n;++i)sort(g[i].begin(),g[i].end());
    s=read();t=read();
    for(int i=1;i<=n;++i){
        if(!deg[i]&&i!=t){
            q.push(i);bj[i]=1;
        }
    }
    while(q.size()){
        int u=q.front();q.pop();int last=-1;//last避免走重边
        for(int i=0;i<(int)g[u].size();++i){
            int v=g[u][i];if(v==last)continue;
            last=v;--deg[v];bj[v]=1;
            if(!deg[v])q.push(v);
        }
    }
    memset(dis,0x3f,sizeof(dis));dis[t]=0;
    q.push(t);
    while(q.size()){
        int u=q.front();q.pop();
        for(int i=0;i<(int)g[u].size();++i){
            int v=g[u][i];if(bj[v])continue;
            if(dis[v]>dis[u]+1){
                dis[v]=dis[u]+1;
                if(!visit[v])visit[v]=1,q.push(v);
            }
        }
    }
    if(dis[s]<N)printf("%d\n",dis[s]);
    else puts("-1");
    return 0;
}

\(D2T3 \)ので、数日の問題を議論する隣の部屋で兄の前に、私はホーナー法として聞こえ、形而上学ので、今日、このキーワードを法彼が思うには、この才能を持っていたときに行う。この右変装、問題の解決策と見なさも見...

形而上学のための剰余\(a_iを\)読み込まれ、読みながらサイドモジュロ、ここでも毎日、高精度を防ぐために。私はの弾性率は持っていたので、なぜ形而上学は?です(19260817 \)を\に、困難な生活を見つける\(1E9 + 7 \)の前にできるようになります。

列挙するためのホーナー法\(X(1 <= xは <= M)\) 場合に可能である\(O(n)が\)時間複雑であることを保証するために計算される\(O(NM)\) 各フラッシュ場合電源がもたらした(\ログ)\を上困難である。結局、私は高速電力を書いていないが、また、定期的にカードを生きること。

ああ、高校でホーナー法は、私は強制3を学んでいた、おそらくそれについて話す(A_0 + a_1x + a_2x ^ 2 + \ cdots + a_nx N- ^ \)\ = \((((a_nx-N-1 + A_ { })+ X-A_ {N-2})+ ... + X A_1)X A_0 + \) \(O(N)\)サイクルは、多項式と計算することができます。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define rg register
#define mod 1000000007
#define ll long long
using namespace std;
inline ll read(){
    rg ll x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=((x<<3)+(x<<1)+ch-'0')%mod,ch=getchar();
    return x*o;
}
const int N=105;
const int M=1e6+5;
int n,m,tot,ans[M];ll a[N];
int main(){
    n=read();m=read();for(rg int i=0;i<=n;++i)a[i]=read();
    for(rg int x=1;x<=m;++x){
        rg ll now=0;
        for(rg int i=n;i>=1;--i)
            now=(1ll*((now+a[i])%mod)*x)%mod;
        if(now+a[0]==0)ans[++tot]=x;
    }
    printf("%d\n",tot);
    for(rg int i=1;i<=tot;++i)printf("%d\n",ans[i]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/PPXppx/p/11780982.html
おすすめ