1. 程式人生 > >Codeforces Round #519 by Botan Investments翻車記

Codeforces Round #519 by Botan Investments翻車記

元素 img turn obi for 比賽 mes pla getch

  A:枚舉答案即可。註意答案最大可達201,因為這個wa了一發瞬間爆炸。

技術分享圖片
#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<0||c>9) {if (c==-) f=-1;c=getchar();}
    
while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 110 int n,a[N],mx; int main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ n=read(); int tot=0; for (int i=1;i<=n;i++) mx=max(mx,a[i]=read()),tot+=a[i];
for (int i=mx;i<=201;i++) { int cnt=0; for (int j=1;j<=n;j++) cnt+=i-a[j]; if (cnt>tot) {cout<<i;return 0;} } return 0; }
View Code

  B:看了半天題。枚舉即可。

技術分享圖片
#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include
<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<0||c>9) {if (c==-) f=-1;c=getchar();} while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 1010 int n,a[N],b[N],cnt=0,c[N]; int main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ n=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int k=1;k<=n;k++) { bool flag=1; for (int i=1;i<=k;i++) b[i]=a[i]-a[i-1]; for (int i=k+1;i<=n;i++) if (a[i]-a[i-1]!=b[(i-1)%k+1]) {flag=0;break;} if (flag) c[++cnt]=k; } cout<<cnt<<endl; for (int i=1;i<=cnt;i++) cout<<c[i]<< ; return 0; }
View Code

  C:看了半天題。想了半天。每次都在字符的分界處翻轉,就可以得到最優解(即a都在前面b都在後面)。

技術分享圖片
#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<0||c>9) {if (c==-) f=-1;c=getchar();}
    while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 1010
int n,a[N];
bool flag[N];
char s[N];
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif*/
    scanf("%s",s+1);
    n=strlen(s+1);
    for (int i=1;i<=n;i++) a[i]=s[i]==b;
    for (int i=1;i<=n;i++)
    {
        int t=i;
        while (t<n&&a[t+1]==a[i]) t++;
        if (t<n||a[i]==0) reverse(a+i+1,a+t+1),flag[t]=1;
        i=t;
    }
    for (int i=1;i<=n;i++) cout<<flag[i]<< ;
    return 0;
}
View Code

  D:看了半天題。暴力匹配,如果失配這些數不可能再被計入答案。這樣分成了很多段,將每段答案加起來即可。

技術分享圖片
#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<0||c>9) {if (c==-) f=-1;c=getchar();}
    while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 100010
#define M 12
int n,m,a[M][N],p[M][N],q[12];
long long ans;
bool check()
{
    for (int i=1;i<=m;i++)
    {
        q[i]++;
        if (q[i]>n) return 0;
    }
    for (int i=2;i<=m;i++)
    if (a[i][q[i]]!=a[i-1][q[i-1]]) return 0;
    return 1;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif
    n=read(),m=read();
    for (int i=1;i<=m;i++)
        for (int j=1;j<=n;j++)
        a[i][j]=read(),p[i][a[i][j]]=j;
    for (int i=1;i<=n;i++)
    {
        int x=i;
        q[1]=i;
        for (int j=2;j<=m;j++) q[j]=p[j][a[1][i]];
        while (x<n&&check()) x++;
        ans+=1ll*(x-i+2)*(x-i+1)/2;
        i=x;
    }
    cout<<ans;
    return 0;
}
View Code

  E:看了半天題。看題時間跟想+碼的時間差不多了。首先給出的那些邊顯然可以直接排除。現在要求的是ansi=Σmin(xi+yj,xj+yi),可以將其變成ansi=Σmin(xi-yi-xj+yj,0)+xj+yi。這樣min裏面的東西只需要二分查一個前綴和。

技術分享圖片
#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<0||c>9) {if (c==-) f=-1;c=getchar();}
    while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 300010
int n,m,t=0;
long long ans[N],b[N],pre[N],sum;
struct data{int x,y;
}a[N];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif
    n=read(),m=read();
    for (int i=1;i<=n;i++) sum+=a[i].x=read(),a[i].y=read(),b[i]=a[i].y-a[i].x;
    sort(b+1,b+n+1);
    for (int i=1;i<=n;i++) pre[i]=pre[i-1]+b[i];
    for (int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        ans[x]-=min(a[x].x+a[y].y,a[x].y+a[y].x),ans[y]-=min(a[x].x+a[y].y,a[x].y+a[y].x);
    }
    /*for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        if (i!=j) ans[i]+=min(a[i].x-a[i].y+b[j],0)+a[i].y+a[j].x;*/
    for (int i=1;i<=n;i++)
    {
        ans[i]+=sum-a[i].x+1ll*a[i].y*(n-1);
        int l=1,r=n,t=0;
        while (l<=r)
        {
            int mid=l+r>>1;
            if (b[mid]+a[i].x-a[i].y<0) t=mid,l=mid+1;
            else r=mid-1;
        }
        ans[i]+=pre[t]+1ll*t*(a[i].x-a[i].y);
    }
    for (int i=1;i<=n;i++) printf("%I64d ",ans[i]);
    return 0;
}
close
View Code

  F:做法似乎很多。比賽時只想到設f[i]為gcd=i時最少選多少元素,考慮通過與i的gcd數量是i的因子個數來優化,預處理可以向哪轉移。這一部分看起來可以瞎優化到不錯的效率,然而又wa又T最後棄療了。

  題解給的是狀壓dp,沒有太懂。似乎也有不少隨機化做法。

  感覺最妙的做法還是這樣:強化這個題,求選k個數時的方案數。這顯然可以莫比烏斯反演,預處理每個數在a中有多少個是其倍數即可,這可以利用調和級數做到log。顯然最終答案若存在一定不超過7,於是復雜度O(n+vlogv)。這應該是保證正確性(取模後變成0什麽的就算了吧)的最優做法了。把一個判定性問題轉化為數數題居然能夠簡化問題非常有意思。

技術分享圖片
#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<0||c>9) {if (c==-) f=-1;c=getchar();}
    while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 300010
#define P 1000000007
int n,a[N],mobius[N],prime[N],tot[N],cnt;
int fac[N],inv[N];
bool flag[N];
int C(int n,int m)
{
    if (m>n) return 0;
    return 1ll*fac[n]*inv[m]%P*inv[n-m]%P;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("f.in","r",stdin);
    freopen("f.out","w",stdout);
#endif
    n=read();
    for (int i=1;i<=n;i++) a[read()]++;
    flag[1]=1;mobius[1]=1;
    for (int i=2;i<=N-10;i++)
    {
        if (!flag[i]) prime[++cnt]=i,mobius[i]=-1;
        for (int j=1;j<=cnt&&prime[j]*i<=N-10;j++)
        {
            flag[prime[j]*i]=1;
            if (i%prime[j]==0) break;
            else mobius[prime[j]*i]=-mobius[i];
        }
    }
    fac[0]=1;for (int i=1;i<=N-10;i++) fac[i]=1ll*fac[i-1]*i%P;
    inv[0]=inv[1]=1;for (int i=2;i<=N-10;i++) inv[i]=P-1ll*(P/i)*inv[P%i]%P;
    for (int i=2;i<=N-10;i++) inv[i]=1ll*inv[i-1]*inv[i]%P;
    for (int i=1;i<=N-10;i++)
        for (int j=i;j<=N-10;j+=i)
        tot[i]+=a[j];
    for (int k=1;k<=7;k++)
    {
        int ans=0;
        for (int i=1;i<=N-10;i++)
        ans=((ans+mobius[i]*C(tot[i],k))%P+P)%P;
        if (ans) {cout<<k;return 0;}
    }
    cout<<-1;
    return 0;
}
View Code

  這場閱讀量實在太大,讀題感覺花了快有30min。A wa一發掉了至少30名非常慘了。

  result:rank 417 rating -6

  

Codeforces Round #519 by Botan Investments翻車記