1. 程式人生 > >Atcoder Grand Contest 021 題解

Atcoder Grand Contest 021 題解

Problem A. (此處省略)反正怎麼搞都行了。。。

Problem B. 對於每個點,列舉其他點,那麼選的點一定是在垂直平分線的一側。由於R 特別大,所以可以把這個垂直平分線移到這個點上,就相當於一堆可行極角區間求交

也可以O(nlogn),大概是把凸包搞出來然後答案就出來了。。。

#include<bits/stdc++.h>
#define maxn 110
using namespace std;
typedef double ldb;
const ldb eps=1e-7;
const ldb pi=acos(-1.0);
ldb nx[maxn],ny[maxn];
int
n; int dcmp(ldb d){ return fabs(d)<eps?0:(d<0?-1:1); } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%lf%lf",&nx[i],&ny[i]); for(int i=1;i<=n;++i){ ldb mn=0,mx=pi; int id=(i==1?2:1); ldb ang=atan2(ny[id]-ny[i],nx[id]-nx[i]); for
(int j=1;j<=n;++j)if(i!=j&&j!=id){ ldb ang1=atan2(ny[j]-ny[i],nx[j]-nx[i]); ldb a=ang-ang1; if(dcmp(a-pi)==0||dcmp(a+pi)==0)mn=1e20; if(dcmp(a-pi)>0)a-=2*pi; else if(dcmp(-pi-a)>0)a+=2*pi; if(dcmp(a)<0)mn=max(mn,-a); else
mx=min(mx,pi-a); } // printf("[%.3lf,%.3lf]",mn,mx); if(dcmp(mn-mx)>=0)puts("0.0"); else printf("%.10lf\n",(mx-mn)/(2*pi)); } }

Problem C.可以發現,一定是先貪心放2*2的小方塊,多的部分用一種方塊來補。最後要特判右下角的3*3方格。

#include<bits/stdc++.h>
using namespace std;
char s[1010][1010];
int n,m,a,b;
int main(){
    scanf("%d%d%d%d",&n,&m,&a,&b);
    for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)s[i][j]='.';
    if(n&1)for(int i=1;i<m&&a;i+=2)s[n][i]='<',s[n][i+1]='>',a--;
    if(m&1)for(int i=1;i<n&&b;i+=2)s[i][m]='^',s[i+1][m]='v',b--;
    for(int i=1;i<n;i+=2)
        for(int j=1;j<m;j+=2){
            if(a>=2){
                a-=2;
                s[i][j]='<',s[i][j+1]='>';
                s[i+1][j]='<',s[i+1][j+1]='>';
            } else if(b>=2){
                b-=2;
                s[i][j]='^',s[i][j+1]='^';
                s[i+1][j]='v',s[i+1][j+1]='v';
            } else if(a&&b&&i==n-2&&j==m-2){
                a--,b--;
                s[i][j]='<',s[i][j+1]='>',s[i][j+2]='^';
                s[i+1][j]='^',s[i+1][j+2]='v';
                s[i+2][j]='v',s[i+2][j+1]='<',s[i+2][j+2]='>';
            } else if(a){
                a--;
                s[i][j]='<',s[i][j+1]='>';
            } else if(b){
                b--;
                s[i][j]='^',s[i+1][j]='v';
            }
        }
    if(a||b)return puts("NO"),0;
    puts("YES");
    for(int i=1;i<=n;++i)puts(s[i]+1);
}

Problem D.直接dp[i][j][k]表示左邊匹配到i,右邊匹配到j,還剩k次。時間複雜度O(n3)

#include<bits/stdc++.h>
using namespace std;
int dp[310][310][310],n;
char s[310];
int dfs(int l,int r,int k){
    if(k<0)return -1000000007;
    if(l>r)return 0;
    else if(l==r)return 1;
    if(~dp[l][r][k])return dp[l][r][k];
    dp[l][r][k]=max(dfs(l+1,r,k),dfs(l,r-1,k));
    dp[l][r][k]=max(dp[l][r][k],dfs(l+1,r-1,k-(s[l]!=s[r]))+2);
//  printf("{%d,%d,%d,%d}",l,r,k,dp[l][r][k]);
    return dp[l][r][k];
}
int main(){
    memset(dp,-1,sizeof(dp));
    scanf("%s%d",s+1,&n);
    printf("%d\n",dfs(1,strlen(s+1),n));
}

Problem E.
首先R< B肯定不可行。
可以發現,一個可行的方案一定滿足R-B+match≤n,其中match表示R,B最大匹配數。

假設我們把這個序列理解為平面上(0,0)到(R,B)的一個路徑,設現在在(x,y)
當R>B,y>x時若要滿足條件,一定有R-B+x+min(B-y,R-x)≤n
即不能有y-x≤R-n+1

R=B同理。
考慮如何算這個,可以用反射法,就是到這個直線就開始分成2條路徑。詳細看官方題解。

#include<bits/stdc++.h>
#define maxn 1001000
#define mod 998244353
using namespace std;
int fac[maxn],inv[maxn],n,m,K,M;
int qpow(int a,int b){
    int ans=1,tmp=a;
    for(;b;b>>=1,tmp=1ll*tmp*tmp%mod)
        if(b&1)ans=1ll*ans*tmp%mod;
    return ans;
}
int C(int x,int y){
    if(x>y||x<0)return 0;
    return 1ll*fac[y]*inv[x]%mod*inv[y-x]%mod;
}
int main(){
    scanf("%d%d",&n,&K),M=K,fac[0]=inv[0]=1;
    for(int i=1;i<=M;++i)fac[i]=1ll*fac[i-1]*i%mod;
    inv[M]=qpow(fac[M],mod-2);
    for(int i=M-1;i>=1;--i)inv[i]=1ll*inv[i+1]*(i+1)%mod;
    int ans=0;
    for(int i=0;i<=K-i;++i){
        int r=K-i,b=i;
        if(r-b+min(r,b)<n)continue; 
        if(r>b)ans=(1ll*ans+C(r,r+b)-C(r+r-n+1,r+b)+mod)%mod;
        else ans=(1ll*ans+C(r,r+b-1)-C(r+b-n+1,r+b-1)+mod)%mod;
    }
    printf("%d\n",ans);
}

Problem F.令dp[i][j]表示i列j行的圖的答案,且這j行非空。則有如下轉移:

1.dp[i][j]->dp[i+1][j],此時有1+C(j,1)+C(j,2)種方案。
2.dp[i][j]->dp[i+1][j+k](k>1),此時只需要考慮新列的方案數,如果最大值放在了j行中的一個,可以將這一行視為新建行,否則可以將最大值多取一個,反正可以發現答案就是i+k+2中選k+2個,即C(i+k+2,k+2)

然後發現這是個卷積的形式。完了。複雜度O(nmlogn)

#include<bits/stdc++.h>
#define mod 998244353
#define maxn 8200
using namespace std;
typedef long long ll;
int n,m,dp[210][maxn<<1],wn[2][maxn<<1],bh[maxn<<1];
int A[maxn<<1],M,fac[maxn<<1],k,inv[maxn<<1];
int qpow(int a,int b){
    int ans=1;
    for(;b;b>>=1,a=1ll*a*a%mod)
        if(b&1)ans=1ll*ans*a%mod;
    return ans;
}
void init(){
    for(int i=1,p;i<M;i<<=1){
        wn[0][i]=1,p=qpow(3,(mod-1)/(i<<1));
        for(int j=1;j<i;++j)wn[0][i+j]=(ll)wn[0][i+j-1]*p%mod;
        wn[1][i]=1,p=qpow(3,mod-1-(mod-1)/(i<<1));
        for(int j=1;j<i;++j)wn[1][i+j]=(ll)wn[1][i+j-1]*p%mod;
    }
}
void fft(int h[],int len,int flag){
    for(int i=0;i<len;++i)if(i<bh[i])swap(h[i],h[bh[i]]);
    for(int i=1;i<len;i<<=1)
        for(int j=0;j<len;j+=(i<<1))
            for(int k=0;k<i;++k){
                int x=h[j+k],y=(ll)h[j+k+i]*wn[flag][i+k]%mod;
                h[j+k]=(x+y)%mod,h[j+k+i]=(x-y+mod)%mod;
            }
    if(flag==1){
        int iv=qpow(len,mod-2);
        for(int i=0;i<len;++i)h[i]=1ll*h[i]*iv%mod;
    }
}
int C(int x,int y){
    if(x>y||x<0)return 0;
    return (ll)fac[y]*inv[x]%mod*inv[y-x]%mod;
}
int main(){
    scanf("%d%d",&n,&m),M=1,k=0,fac[0]=inv[0]=1;
    while(M<2*n)M<<=1,k++;
    for(int i=1;i<=n+2;++i)fac[i]=1ll*fac[i-1]*i%mod;
    inv[n+2]=qpow(fac[n+2],mod-2);
    for(int i=n+1;i>=1;--i)inv[i]=1ll*inv[i+1]*(i+1)%mod;
    for(int i=0;i<M;++i)bh[i]=(bh[i>>1]>>1)|((i&1)<<(k-1));
    init();
    dp[0][0]=1;
    for(int i=0;i<m;++i){
        for(int j=0;j<=n;++j)
            dp[i+1][j]=(ll)(j*(j+1)/2+1)*dp[i][j]%mod,
            dp[i][j]=(ll)dp[i][j]*inv[j]%mod;
        for(int j=0;j<=M;++j)A[j]=0;
        for(int j=1;j<=n;++j)A[j]=inv[j+2];
        fft(dp[i],M,0),fft(A,M,0);
        for(int j=0;j<M;++j)A[j]=(ll)A[j]*dp[i][j]%mod;
        fft(A,M,1);
        for(int j=1;j<=n;++j)
            dp[i+1][j]=(dp[i+1][j]+(ll)A[j]*fac[j+2])%mod;
    }
    int ans=0;
//  for(int i=0;i<=n;++i)printf("[%d]",dp[m][i]);
    for(int i=0;i<=n;++i)ans=(ans+(ll)C(i,n)*dp[m][i])%mod;
    printf("%d",ans);
} 

相關推薦

Atcoder Grand Contest 021 題解

Problem A. (此處省略)反正怎麼搞都行了。。。 Problem B. 對於每個點,列舉其他點,那麼選的點一定是在垂直平分線的一側。由於R 特別大,所以可以把這個垂直平分線移到這個點上,就相當於一堆可行極角區間求交 也可以O(nlogn),大概是把凸

Atcoder Grand Contest 002 題解

push_back 個人選擇 first box 可能 getc 等於 clear const A - Range Product 經過0答案肯定是0,都是正數肯定是正數,都是負數的話就奇負偶正。 //waz #include <bits/stdc++.h>

Atcoder Grand Contest 003 題解

位置 發現 clu cpp 模擬 gii icu define -a A - Wanna go back home 如果有S就必須要有N,反之亦然,如果有E必須要有W,反之亦然。判斷一下就好了。 //waz #include <bits/stdc++.h>

AtCoder Grand Contest 013 題解

fine esp square == ask air %d nis 就是 A - Sorted Arrays 貪心,看看不下降和不上升最長能到哪,直接轉移過去即可。 1 //waz 2 #include <bits/stdc++.h> 3 4 us

AtCoder Grand Contest 015 題解

pan gin ken -- 出現 style 地方 連通塊 發現 A - A+...+B Problem 可以取到的值一定是一段區間。所以答案即為max-min+1 1 //waz 2 #include <bits/stdc++.h> 3 4 u

[atcoder]AtCoder Grand Contest 027題解

【題目連結】 A 【題解】 題意: 是把xxx個糖果分給nnn個人,一個人如果恰好分到aia_{i}ai​個糖果就會高興。求最多使多少個人高興。 題解: 一定是優先滿足需求小的人,特判有額外的剩餘糖果。 時間複雜度:O(NlogN)O(NlogN)O(Nlog

AtCoder Grand Contest 031 簡要題解

isp href uil 出現 mat false tor 每次 spa AtCoder Grand Contest 031 Atcoder A - Colorful Subsequence description 求\(s\)中本質不同子序列的個數模\(10^9+7\)。

AtCoder Grand Contest 013D: Piling Up 題解

情況 之前 include out fin fine del ons etc 題意簡化: [luogu] Piling Up 一開始有n個顏色為黑白的球,但不知道黑白色分別有多少,m次操作,每次先拿出一個球,再放入黑白球各一個,再拿出一個球,最後拿出的球按順序排列會形成一個

AtCoder Grand Contest 020 C - Median Sum

CI https TE ems and fin sub oot tco 題目:here 題解:要轉化一下,找所有子集的中間值,等價於找一個子集,滿足這個子集的和最接近整個序列的和的一半。也就是一個背包判斷可行性的問題。重點來了,bitset優化,至於為什麽?我也不懂啊啊啊

[Atcoder Grand Contest 001] Tutorial

IV AI display aps span col tin lap nbsp Link: AGC001 傳送門 A: #include <bits/stdc++.h> using namespace std; long long res=0; int n

AtCoder Grand Contest 024 Problem E(動態規劃)

stand 之間 graph ret scan 慢慢 rap and there www.cnblogs.com/shaokele/ AtCoder Grand Contest 024 Problem E   Time Limit: 2 Sec   Memory Lim

AtCoder Grand Contest 006 F - Blackout

sin 所在 long long || 如果 open int 雙向 mem Description 在 \(n*n\) 的棋盤上給出 \(m\) 個黑點,若 \((x,y)\),\((y,z)\) 都是黑點,那麽 \((z,x)\) 也會變成黑點,求最後黑點的數量 題面

AtCoder Grand Contest #026 C - String Coloring

暴力 input 很好 left rgs map() paint int() letters Time Limit: 3 sec / Memory Limit: 1024 MB Score : 600600 points Problem Statement Y

AtCoder Grand Contest 007

mem ssi || 狀態 puts def end tor ace AtCoder Grand Contest 007 A - Shik and Stone 翻譯 見洛谷 題解 傻逼玩意 #include<cstdio> int n,m,tot;char ch

AtCoder Regular Contest 103 題解

print -s struct namespace type iostream con clas inline C-/\/\/\ #include<algorithm> #include<iostream> #include<cstdlib&g

AtCoder Grand Contest 011

判斷 define 開機 %s square d+ 更新 getc 在一起 AtCoder Grand Contest 011 upd:這篇咕了好久,前面幾題是三周以前寫的。。。 AtCoder Grand Contest 011 A - Airport Bus 翻譯 有\

AtCoder Grand Contest 001 C Shorten Diameter 樹的直徑

題意 給你一棵樹,每次可以刪除一個葉子節點,求最少需要多少次操作可以讓樹的直徑\(<=k,(n <= 2e3)\) 首先觀察資料範圍是可以接受\(O(n^2)\)的演算法的 我們考慮列舉每個點作為樹的根 統計這個點一定在直徑上時要刪多少點 如果\(k\)是偶數,那麼深度大於\(

AtCoder Grand Contest 006 C:Rabbit Exercise

題目傳送門:https://agc006.contest.atcoder.jp/tasks/agc006_c 題目翻譯 數軸上有\(N\)只兔子,從\(1\)到\(N\)編號,每隻兔子初始位置是\(x_i\)。現在兔子們要開始做運動,運動都有\(M\)個步驟,對於第\(i\)個步驟,我們用\(a_i\)來

AtCoder Grand Contest 014 E:Blue and Red Tree

make 開始 n-1 不可 task blog 應該 space find 題目傳送門:https://agc014.contest.atcoder.jp/tasks/agc014_e 題目翻譯 有一棵有\(N\)個點的樹,初始時每條邊都是藍色的,每次你可以選擇一條由藍色

AtCoder Grand Contest 012 D:Colorful Balls

題目傳送門:https://agc012.contest.atcoder.jp/tasks/agc012_d 題目翻譯 給你一排一共\(N\)個球,每個球有一個顏色\(c_i\)和一個重量\(w_i\),如果兩個球顏色相同,重量相加不超過\(x\)那我就可以交換這倆個球的位置。如果兩個球顏色不同,重量相加