2018.8.21提升A&省選組模擬考試

爲何8月份的考試拖到如今才發題解呢?ios

由於實際上這是咱們昨天才考的...只不過正好和某校8月份的模擬考試重題而已...算法

 

T1 題意簡述:jzoj5835數組

 

Description

Input

Output

Data Constraint

 

   解題思路:很簡單的一道篩法題。優化

             分析題目,發現只須要篩出[1,min(K,sqrt(R))]範圍內的質數便可。ui

#include<algorithm>//STL通用算法
#include<bitset>//STL位集容器
#include<cctype>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>//STL雙端隊列容器
#include<list>//STL線性列表容器
#include<map>//STL映射容器
#include<iostream>
#include<queue>//STL隊列容器
#include<set>//STL集合容器
#include<stack>//STL堆棧容器
#include<utility>//STL通用模板類
#include<vector>//STL動態數組容器
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
ll L,R,n,len,ans,sch[10000005];
ll cnt,pri[10000005],jdg[10000005];
void getpri()
{
    jdg[1]=1;
    for(ll i=2;i<=n;i++)
    {
        if(!jdg[i]) pri[++cnt]=i;
        for(ll j=1;j<=cnt;j++)
        {
            if(pri[j]*i>n) break;
            jdg[i*pri[j]]=1;
            if(!(i%pri[j])) break;
        }
    }
}
int main()
{
    freopen("prime.in","r",stdin);
    freopen("prime.out","w",stdout);
    scanf("%lld%lld%lld",&L,&R,&n);
    n=min((ll)sqrt(R),n),len=R-L+1;
    getpri();
    for(ll i=1;i<=cnt;i++)
    {
        ll tmp=(L/pri[i]+(L%pri[i]!=0))*pri[i]-L+1;
        while(tmp<=len) sch[tmp]=1,tmp+=pri[i];
        if(pri[i]>=L) sch[pri[i]-L+1]=0;
    }
    for(ll i=1;i<=len;i++) if(!sch[i]) ans^=L+i-1;
    printf("%lld\n",ans);
    return 0;
}

 


 

T2 題意簡述:jzoj5836spa

 

Description

Input

Output

 

Data Constraint

 

   解題思路:貪心+矩陣乘法。.net

             首先考慮如何計算一個序列中的子序列個數。(子序列個數指互不重複的子序列個數。如下同理)code

             題解中所給的式子是dp[num[i]]=∑(j=1,k)dp[j],其中dp[i]表示以i結尾的子序列個數。blog

             其實有一種式子更易理解:dp[i]=dp[i-1]*2-dp[pos[num[i]]-1](pos[i]!=0)。隊列

             其中dp[i]表示序列第i項的子序列個數,pos[i]表示數字i在序列中上一次出現的位置。

             這個式子的意思是,在上一項的每一個子序列後面都填上一個num[i],可是還要減去重複的。

             重複的子序列其實就是上次此數字出現時已經計入的子序列。固然,若還未出現過就沒必要減去了。

             用這個方法能夠算出整個序列的子序列個數。

             接下來考慮m個待填數字。

             觀察式子,發現要使結果最大,只需使dp[pos[num]-1]最小便可。

             易知,dp數組是單調遞增的。所以,只需保證pos[num]-1最小即可保證結果最大。

             也就是說,每次取最先出現的那個元素做爲當前項便可。

             直接遞推複雜度O(n+m),這樣的複雜度是沒法接受的。考慮優化。

             衆所周知,遞推式能夠用矩陣乘法優化。最終複雜度O(n+k+k^3logm)。

             爲何會有個(+k)?由於一開始的k項是沒法用矩陣乘法優化的。

             pos在一開始的k項取值範圍爲[0,n],顯然咱們沒法建一個n*n的矩陣。

             可是在經歷一個循環節後,pos的取值範圍就變成了[n+1,n+k],所以只需建一個(k+1)*(k+1)的矩陣便可。

#include<algorithm>//STL通用算法
#include<bitset>//STL位集容器
#include<cctype>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>//STL雙端隊列容器
#include<list>//STL線性列表容器
#include<map>//STL映射容器
#include<iostream>
#include<queue>//STL隊列容器
#include<set>//STL集合容器
#include<stack>//STL堆棧容器
#include<utility>//STL通用模板類
#include<vector>//STL動態數組容器
#define INF 0x3f3f3f3f
#define ll long long
#define MOD 1000000007
using namespace std;
ll n,m,k,ans,num[1000010],pos[110],que[110],dp[2000010];
struct uio{
    ll pos,num;
}srt[110];
struct oiu{
    ll sqr[110][110];
    oiu(){memset(sqr,0,sizeof(sqr));}
    friend oiu operator *(const oiu &x,const oiu &y)
    {
        oiu z;
        for(ll i=1;i<=k+1;i++)
            for(ll j=1;j<=k+1;j++)
                for(ll l=1;l<=k+1;l++)
                    (z.sqr[i][j]+=x.sqr[i][l]*y.sqr[l][j]%MOD)%=MOD;
        return z;
    }
}mat,bgn;
bool cmp(uio x,uio y){return x.pos<y.pos;}
void init(oiu &x) {for(ll i=1;i<=k+1;i++) x.sqr[i][i]=1;}
oiu qpow(oiu x,ll y)
{
    oiu z;init(z);
    while(y) 
    {if(y&1) z=z*x;x=x*x;y/=2;}
    return z;
}
signed main()
{
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    scanf("%lld%lld%lld",&n,&m,&k);
    for(ll i=1;i<=n;i++) scanf("%lld",&num[i]);
    dp[0]=1;
    for(ll i=1;i<=n;i++)
    {
        if(pos[num[i]]) dp[i]=(dp[i-1]*2-dp[pos[num[i]]-1]+MOD)%MOD;
        else dp[i]=dp[i-1]*2%MOD;
        pos[num[i]]=i;
    }
    for(ll i=1;i<=k;i++) srt[i]={pos[i],i};
    sort(srt+1,srt+1+k,cmp);
    for(ll i=1;i<=k;i++) que[i]=srt[i].num;
    for(ll i=n+1;i<=n+min(m,k);i++)
    {
        ll x=que[i-n];
        if(pos[x]) dp[i]=(dp[i-1]*2-dp[pos[x]-1]+MOD)%MOD;
        else dp[i]=dp[i-1]*2%MOD;
        pos[x]=i;
    }
    m-=k;if(m<=0) {printf("%lld\n",dp[n+m+k]-1);return 0;}
    mat.sqr[1][1]=2,mat.sqr[k+1][1]=-1;
    for(ll i=1;i<=k;i++) mat.sqr[i][i+1]=1;
    for(ll i=1;i<=k+1;i++) bgn.sqr[1][i]=dp[n+k-i+1];
    mat=qpow(mat,m);
    for(ll i=1;i<=k+1;i++) (ans+=bgn.sqr[1][i]*mat.sqr[i][1]%MOD+MOD)%=MOD;
    printf("%lld\n",(ans-1+MOD)%MOD);
    return 0;
}

 


 

T3 題意簡述:jzoj5837

 

Description

Input

Output

Data Constraint

 

   解題思路:不會。博主看了題解後仍是沒寫出來。

             在這裏貼一個官方題解,有興趣的大佬可瞭解一下。

相關文章
相關標籤/搜索