1. 程式人生 > >10.28模擬賽

10.28模擬賽

因此 can bool etc 最終 lose ans math 收集

幸運數字(number)

Description

LYK 最近運氣很差,例如在 NOIP 初賽中僅僅考了 90 分,剛剛卡進復賽,於是它決定使 用一些方法來增加自己的運氣值。

它覺得,通過收集幸運數字可以快速的增加它的 RP 值。

它給幸運數字下了一個定義:如果一個數 x 能被 3 整除或被 5 整除或被 7 整除,則這個 數為幸運數字。

於是它想讓你幫幫它在 L~R 中存在多少幸運數字

Input

第一行兩個數 L,R。

Output

一個數表示答案 。

數據範圍

對於 50%的數據 1<=L<=R<=10^5。

對於 60%的數據 1<=L<=R<=10^9。

對於 80%的數據 1<=L<=R<=10^18。

對於 90%的數據 1<=L<=R<=10^100。

對於另外 10%的數據 L=1, 1<=R<=10^100。

對於 100%的數據 L, R 沒有前導 0。

哇,水題.

很明顯是容斥原理.

\(L\)\(R\)的答案可以化簡為\(1\)\(R\)的答案減去\(1\)\(L-1\)的答案.(貌似這也是容斥)

所以根據容斥原理的式子(這裏就不放了)。

最終推得式子為
\[ A=\frac{R}{3}+\frac{R}{5}+\frac{R}{7}-\frac{R}{15}-\frac{R}{21}-\frac{R}{35}+\frac{R}{105} \]

\[ B=\frac{L-1}{3}+\frac{L-1}{5}+\frac{L-1}{7}-\frac{L-1}{15}-\frac{L-1}{21}-\frac{L-1}{35}+\frac{L-1}{105} \]

\[ ans=A-B \]

但是看到數據範圍你不慌嘛?

高精?完了要涼

硬著頭皮碼(tiao)了1個半小時.

問題不大.

代碼

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define clear(a) memset(a,0,sizeof a)
#define N 10008
#define R register
using namespace std;
int len,a[N],b[N],t[N],ans[N];
int sa[N],sb[N],c[2]={1,1};
char l[N],r[N];
inline void pre(int *a,int *b)
{
    clear(sa);clear(sb);
    sa[0]=a[0];
    for(int i=1;i<=a[0];i++)
        sa[i]=a[a[0]-i+1];
    for(int i=1;i<=b[0];i++)
        sb[i]=b[b[0]-i+1];
    for(R int i=1;i<=sa[0];i++)
    {
        sa[i]-=sb[i];
        if(sa[i]<0)
        {
            sa[i]+=10;
            sa[i+1]--;
        }
    }
    while(sa[0]>1 and sa[a[0]]==0)sa[0]--;
    a[0]=sa[0];
    for(int i=1;i<=sa[0];i++)a[i]=sa[sa[0]-i+1];
}
inline void div(int *a,int *b,int x)
{
    int plus=0;
    a[0]=b[0];
    for(R int i=1;i<=b[0];i++)
    {
        plus=plus*10+b[i];
        a[i]=plus/x;plus%=x;
    }
}
inline void add(int *a,int *b)
{
    clear(sa),clear(sb);
    int len1=a[0],len2=b[0],len=1;
    for(R int i=1;i<=len2;i++)
        sb[i]=b[len2-i+1];
    for(;len<=len1 or len<=len2;len++)
    {
        sa[len]+=a[len]+sb[len];
        sa[len+1]=sa[len]/10;
        sa[len]=sa[len]%10;
    }
    while(len>1 and sa[len]==0)len--;
    sa[0]=len;
    for(R int i=0;i<=sa[0];i++)a[i]=sa[i];
}
inline void jian(int *a,int *b)
{
    clear(sb);
    for(R int i=1;i<=b[0];i++)
        sb[i]=b[b[0]-i+1];
    for(R int i=1;i<=a[0];i++)
    {
        a[i]=a[i]-sb[i];
        if(a[i]<0)
        {
            a[i]=a[i]+10;
            a[i+1]--;
        }
    }
    while(a[0]>1 and a[a[0]]==0)a[0]--;
}
int main()
{
    freopen("number.in","r",stdin);
    freopen("number.out","w",stdout);
    scanf("%s",l);
    scanf("%s",r);
    int len1=strlen(l),len2=strlen(r);
    a[0]=len1,b[0]=len2;
    for(int i=1;i<=len1;i++) a[i]=l[i-1]-'0'; 
    for(int i=1;i<=len2;i++) b[i]=r[i-1]-'0';
    
    pre(a,c);
    
/**/    
    div(t,b,3);add(ans,t);
    div(t,b,5);add(ans,t);
    div(t,b,7);add(ans,t);
    
    div(t,a,3);jian(ans,t);
    div(t,a,5);jian(ans,t);
    div(t,a,7);jian(ans,t);
/**/
    
/**/    
    div(t,a,15);add(ans,t);
    div(t,a,21);add(ans,t);
    div(t,a,35);add(ans,t);
    
    div(t,b,15);jian(ans,t);
    div(t,b,21);jian(ans,t);
    div(t,b,35);jian(ans,t);
/**/    
    
/**/    
    div(t,b,105);add(ans,t);
    
    div(t,a,105);jian(ans,t);
/**/
    for(R int i=ans[0];i>=1;i--)
        printf("%d",ans[i]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

位運算(bit)

Description

lyk 最近在研究位運算。它發現除了 xor,or,and 外還有很多運算。

它新定義了一種運算符“#” 。 具體地,可以由 4 個參數來表示。 令 a[i][j]表示 i#j。 其中 i,j 與 a 的值均∈[0,1]。

當然問題可以擴展為>1 的情況,具體地,可以將兩個數分解為 p 位,然後對於每一位 執行上述的位運算,再將這個二進制串轉化為十進制就可以了。

例如當 a[0][0]=0, a[1][1]=0, a[0][1]=1, a[1][0]=1 時,3#4 在 p=3 時等於 7,2#3 在 p=4 時等於 1(實際上就是異或運算)。

現在 lyk 想知道的是,已知一個長為 n 的數列 b。它任意選取一個序列 c,滿 足 c1<c2<...<ck,其中 1≤c1 且 ck≤n,定義這個序列的價值為 b{c1}#b{c2}#...#b{ck} 的平方。

這裏我們假設 k 是正整數,因此滿足條件的 c 的序列個數一定是 2^n-1 。

lyk 想知道 所有滿足條件的序列的價值總和是多少。

由於答案可能很大, 你只需輸出答案對 1,000,000,007 取模後的結果即可

Input

第一行兩個數 n,p。

第二行 4 個數表示 \(a[0][0], a[0][1], a[1][0], a[1][1]\)

第三行 n 個數表示 bi(0<=bi<2^p)。

Output

一個數表示答案 。

數據範圍

總共 10 組數據。

對於第 1,2 組數據 n<=5。

對於第 3,4 組數據 n<=10000, p=1。

對於第 5 組數據 a 值均為 0。

對於第 6 組數據 a 值均為 1。

對於第 7 組數據 \(a[0][0]=0,a[1][0]=0,a[1][1]=1,a[0][1]=1\)

對於第 8,9 組數據 n<=1000, p<=10。

對於所有數據 n<=10000, 1<=p<=30。

對於現在的我來說不可做不可做。

連特判都錯了

\(std\)

將一個數的平方拆成若幹冪次的平方,例如\(7^{2}=(1+2+4)^2\)

觀察答案的形式為\(1*1+1*2+1*4+2*1+2*2+2*4+4*1+4*2+4*4\)
枚舉每兩位,令\(dp[i][j][k]\)表示到第i位,此時第一位為j,第二位為k的方案總數,累加即可。

螞蟻運輸(ant)

LYK 在觀察一些螞蟻。

螞蟻想要積攢一些貨物來過冬。

積攢貨物的方法是這樣的。 對於第 i 只螞蟻,它要從 li出發,拿起貨物,走到 ri處放下貨物,需要消耗的時間為|ri-li|。 而且所有螞蟻都是可以同時進行的,也就是說,假如有 m 只螞蟻,那麽運輸完貨物的時間 為 max{|ri-li|}。

LYK 決定幫螞蟻一把,它發明了空間傳輸裝置。具體地,當螞蟻走到 X 處時,它可以不 耗費任意時間的情況下瞬間到達 Y,或者從 Y 到達 X。也就是說,一個螞蟻如果使用了空間 傳輸裝置,它耗費的時間將會是 min{|li-X|+|ri-Y|,|li-Y|+|ri-X|},當然螞蟻也可以選擇徒步走 到目標點。

由於空間傳輸裝置非常昂貴, LYK 打算只建造這麽一臺機器。並且 LYK 想讓螞蟻運輸完 貨物的時間盡可能短,你能幫幫它嗎?

Input

第一行兩個數 n,m, n 表示 li,ri 的最大值。

接下來 m 行,每行兩個數 li,ri。

Output

一個數表示答案 。

數據範圍

對於 20%的數據 n,m<=100。

對於 40%的數據 n,m<=1000。

對於 60%的數據 n<=100000, m<=1000。

對於 80%的數據 n,m<=100000

對於 100%的數據 n,m<=1000000, 1<=li,ri<=n(li=ri 時你甚至可以無視這只螞蟻)。

這套題太惡心了!

尤其是這題.

出題人造數據竟然不說\(l\)可能大於\(r\)其實是我沒看到中間的逗號

然後由\(100pts\)變成了\(30pts\)!!!

要不\(rank3\)了!

二分答案
讀入時一定要!一定要!保證\(l_i<=r_i\)
\(ok(mid)\)
設建的傳送站為\(X  Y\)
\(abs(l-X)+abs(r-Y)<=mid\)
\(abs\)拆開,存在四種情況

  1. \(l-X+r-Y<=mid\)
  2. \(l-X+Y-r<=mid\)
  3. \(X-l+r-Y<=mid\)
  4. \(X-l+Y-r<=mid\)

則存在以下倆不等式.
\(l+r-mid<=X+Y<=l+r+mid\)
\(l-r-mid<=X-Y<=l-r+mid\)
只要存在X,Y對於所有的l,r滿足上面兩條件即可

然後逼近即可.

一定要判斷輸入!!!!!!

\(std\)

觀察到答案具有可二分性。我們可以二分答案。
由於路徑都是無向的,因此對於任意一條方案li,ri若li>ri則可以交換li和ri。
我們設二分的答案為x。
對於那些li+x>=ri的方案我們直接默認為可行。
我們規定X<=Y。
對於li+x<ri的方案。只有一種可能能夠完成,即,從li出發,到達X,到達Y,到達ri。
也就是說,如果X確定,Y存在於一段區間內。
我們來看li>=X的情況。
先求出X=n時符合條件的Y的區間。當X慢慢減少時,這個區間肯定也在慢慢合攏,並且滿足li>=X的條件也會越來越多。我們可以線性求出所有這個區間。
對於li<X的情況也同理。
這樣就能做到線性判斷,總復雜度nlgn。(這裏默認n與m同階)

代碼

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<ctime>
#include<algorithm>
#define R register
using namespace std;

inline void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int n,m,cnt;
struct cod{int l,r;}ant[1000008];
inline bool ok(int x)
{
    R int le=-2147483644,ri=2147483644;
    for(R int i=1;i<=cnt;i++)
    {
        if(ant[i].r-ant[i].l<=x)continue;
        le=max(le,ant[i].l+ant[i].r-x);
        ri=min(ri,ant[i].l+ant[i].r+x);
    }
    if(le>ri)return false;
    
    le=-2147483644,ri=2147483644;
    for(R int i=1;i<=cnt;i++)
    {
        if(ant[i].r-ant[i].l<=x)continue;
        le=max(le,ant[i].l-ant[i].r-x);
        ri=min(ri,ant[i].l-ant[i].r+x);
    }
    if(le>ri)return false;
    return true;
}

int main()
{
    freopen("ant.in","r",stdin);
    freopen("ant.out","w",stdout);
    in(n),in(m);
    {
        for(R int i=1,x,y;i<=m;i++)
        {
            in(x),in(y);
            if(x>y)swap(x,y);
            ant[++cnt].l=x,ant[cnt].r=y;
        }
        int l=0,r=1e9,ans;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(ok(mid))r=mid-1,ans=mid;
            else l=mid+1;
        }
        printf("%d",ans);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

10.28模擬賽