2018.8.20提升AB組模擬考試

仍是來填坑了...ios

 

T1 題意簡述:jzoj4421數組

 

Description

SillyHook要給小朋友出題了,他想,對於初學者,第一題確定是a+b 啊,但當他出完數據後神奇地發現.in不見了,只留下了一些.out,他想還原.in,但狀況實在太多了,因而他想要使得[a,b] ([a,b] 表示a,b 的最小公倍數)儘量大。

Input

輸入文件的第一行一個整數T 表示數據組數。
接下來T行每行一個整數n ,表示.out中的數值,即a+b=n 。

Output

共T行,每行一個整數表示最大的[a,b] 的值。

Data Constraint

 30%的數據知足 T<=10,n<=1000
100% 的數據知足T<=10000 ,n<=10^9

 

   解題思路:打表找規律。優化

             先暴力枚舉下,發現答案分3種狀況:ui

             1.n是奇數:a=floor(n/2),b=ceil(n/2)。spa

             2.n是偶數且n/2是偶數:a=n/2-1,b=n/2+1。.net

             3.n是偶數且n/2是奇數:a=n/2-2,b=n/2+2。3d

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
ll T,n,ans;
int main()
{
    scanf("%lld",&T);
    while(T--)
    {
        ans=0;
        scanf("%lld",&n);
        if(n==2){printf("1\n");continue;}
        if(n<=1){printf("0\n");continue;}
        ll tmp1=0,tmp2=0;
        tmp1=n/2,tmp2=n-tmp1;
        if(tmp1==tmp2)
        {
            tmp1--,tmp2++;
            if(!(tmp1%2)) tmp1--,tmp2++;
        }
        ans=tmp1*tmp2;
        printf("%lld\n",ans);
    }
    return 0;
}

 


 

T2 題意簡述:jzoj4424code

 

Description

Input

Output

Data Constraint

 

   解題思路:分治FFT/NTT。blog

             因爲博主太蒟蒻不會FFT或是NTT,所以沒有代碼。隊列

             想看題解的戳這裏

 


 

T3 題意簡述:jzoj4406

 

Description

有 2n 我的玩拔河,拔河的繩子由左右兩段組成,每段繩子上有 n 個位置,第 i 我的能夠在左邊繩子的 l i 位置處,也能夠在右邊繩子的 r i 位置處。每一個位置上有且僅有一我的。每一個人有一個實力值 s i ,問對於每一種合法方案兩邊實力值和之差的絕對值最小是多少,若是無解輸出 -1 。

Input

第1行一個整數 n。
第2 ~ 2n+1行,每行三個整數l i, r i, s i

Output

一個整數表示所求的答案

Data Constraint

30%:1 <= n <= 10
70%:1 <= n <= 10 3
100%:1 <= n <= 3 * 10 4, 1 <= s i <= 15

 

   解題思路:二分圖+揹包。

             考慮在li,ri之間連一條權值爲si的邊,並記錄各點度數。

             發現如有點度數爲0則無解,如有點度數爲1則該點結果惟一。

             所以能夠把全部度數小於2的點進行處理,分別加到左右ans上。

             接下來圖上只會剩下若干個偶環,考慮用揹包解決剩下的問題。

             dfs求出在一個偶環中奇數邊權值-偶數邊權值的差,將其做爲一個物品,作01揹包便可。

             發現這樣子時空都會炸,考慮單調隊列滾動數組優化多重揹包。

             感謝ZLX大佬教會博主上一行所述的操做。ZLX大佬OrzOrzOrz

             ZLX大佬還提供了揹包的思路圖:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
int n,cnt=-1,ansl,ansr,d[60001],head[60001],vis[120001];
int m,sum,tot,wei[60001],num[60001],f[1200001],mi[60001],q[60001];
struct uio{
    int nxt,to,val;
}edge[120001];
queue<int> que;
map<int,int> mp;
void add(int x,int y,int z)
{
    edge[++cnt].nxt=head[x];
    edge[cnt].to=y;
    edge[cnt].val=z;
    head[x]=cnt;
}
void dfs(int x,int num)
{
    for(int i=head[x];i!=-1;i=edge[i].nxt)
    {
        int y=edge[i].to;
        if(vis[i]) continue;
        if(!num) sum+=edge[i].val;
        else sum-=edge[i].val;
        vis[i]=vis[i^1]=1;
        d[x]--,d[y]--;
        dfs(y,num^1);
    }
}
int dp(int m)
{
    memset(f,0,sizeof(f));
    int h,t;
    for(int i=1;i<=tot;i++)
    {
        if(!wei[i]) continue;
        int mn=min(num[i],m/wei[i]);
        for(int d=0;d<wei[i];d++)
        {
            h=t=1;
            for(int j=0;j<=(m-d)/wei[i];j++)
            {
                int tmp=f[j*wei[i]+d]-wei[i]*j;
                while(h<t&&q[t-1]<=tmp) t--;
                q[t]=tmp,mi[t]=j,t++;
                while(h<t&&j-mi[h]>mn) h++;
                f[j*wei[i]+d]=max(f[j*wei[i]+d],q[h]+wei[i]*j);
            }
        }
    }
    return f[m];
}
void solve()
{
    int l=dp((m+ansr-ansl)/2),r=dp((m+ansl-ansr)/2);
    int ans1=abs(ansl+l-(ansr+m-l));
    int ans2=abs(ansr+r-(ansl+m-r));
    printf("%d\n",min(ans1,ans2));
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d",&n);
    for(int i=1;i<=2*n;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v+n,w),add(v+n,u,w);
        d[u]++,d[v+n]++;
    }
    for(int i=1;i<=2*n;i++)
    {
        if(!d[i]){printf("-1\n");return 0;}
        if(d[i]==1) que.push(i);
    }
    while(!que.empty())
    {
        int now=que.front();que.pop();
        for(int i=head[now];i!=-1;i=edge[i].nxt)
        {
            if(vis[i]) continue;
            int y=edge[i].to;
            if(now<=n) ansl+=edge[i].val;
            else ansr+=edge[i].val;
            vis[i]=vis[i^1]=1,d[now]--,d[y]--;
            if(d[y]==1) que.push(y);
        }
    }
    for(int i=1;i<=2*n;i++)
        if(d[i]==2)
        {
            sum=0,dfs(i,0);
            sum=abs(sum);m+=sum;
            if(!mp[sum]) mp[sum]=++tot,wei[tot]=sum;
            num[mp[sum]]++;
        }
    solve();
    return 0;
}
相關文章
相關標籤/搜索