NOIP2017提高組 模擬賽21(總結)

2021-08-08 20:10:32 字數 3197 閱讀 8851

【題目描述】

【解題思路】

問題轉化為有多少個【l,r】使得a的l~r這個區間乘起來是k的倍數。 k√

的時間分解k的質因數。

列舉l,可以發現r具有單調性,也就是若【l,r】合法,那麼【l,r+1】也合法。

用尺取法就可以解決。

時間複雜度:o(

2n+k

√)

【**】

#include

#include

using

namespace

std;

typedef

long

long ll;

int n,k;

const

int n=1e5;

int d[n+100],kl,sl,ty[n+100],cnt;

ll f[n+100];

ll ans;

int pck(int x,int v)

}return x;

}bool check()

int main()

} sl=-1;

for(int i=1;i<=n;i++) scanf("%d",&d[i]);

int la=0;

for(int i=1;i<=n;i++)

if(check()) ans+=(n-la+1);

yu=pck(d[i],-1);

if(!(yu%kl)) sl--;

}printf("%lld\n",ans);

return

0;}

【題目描述】

【解題思路】

異或有結合律,交換律。

但題目需要求和,加法不能跟異或同時做。

其實把每乙個數字x,分解成∑2

ki,也就是把x轉化為二進位制來做。建立logx個線段樹,分別表示二進位制的第k位的情況(也就是【l,r】這一區間,xi轉化成二進位制,第k位多少個1,l≤i≤r)。

若【l,r】這一區間xor 2^k,則把線段樹k中的【l,r】範圍的1變成0,0變成1。(統計1的個數sum1就行,打反轉標記。反轉的話1的個數就等於r-l+1-sum1)

【**】

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int n=1e5+10;

const

int kp=20;

int n;

int d[n];

struct data

t[21][n<<2];

ll ans;

int gd(int x,int y)

void build(int w,int ro,int l,int r)

int mid=(l+r)>>1;

build(w,ro<<1,l,mid); build(w,ro<<1|1,mid+1,r);

t[w][ro].s=t[w][ro<<1].s+t[w][ro<<1|1].s;

}void down(int w,int ro,int l,int r)

}void updata(int w,int ro,int l,int r,int li,int ri)

int mid=(l+r)>>1;

down(w,ro,l,r);

updata(w,ro<<1,l,mid,li,ri); updata(w,ro<<1|1,mid+1,r,li,ri);

t[w][ro].s=t[w][ro<<1].s+t[w][ro<<1|1].s;

}int query(int w,int ro,int l,int r,int li,int ri)

int main()

else

if(c==2)}}

}

【題目描述】

【解題思路】

首先想到的就是數字dp(lr那麼大,除此之外也沒什麼可以做的了)。

dp的狀態:f[第i位][字串的狀態][當前的麻辣值][是否有前導零][是否達到上界]=方案數

但,如果把所有的字串的狀態直接記下來,是很難轉移的,不可能再重新匹配。

所以想到建ac自動機來維護,字串的狀態也就是在ac自動機上的位置t(先預處理出字串所對應的麻辣值)。列舉下一位的數字x(0~19),直接轉移到t->c[x]的位置,再加上麻辣值,累計方案數。

最後統計所有位置,麻辣值不超過k的方案數的和。

【**】

#include

#include

#include

using namespace std;

const int mods=1000000007;

const int ln=505;

struct data t[ln];

int dl[210],dr[210],q[210];

int root,n,m,k,cnt;

int f[2][205][705][2][2];

void buildfail()

k=t[k].fail;

}if(flag) t[v].fail=t[k].r[i]; else t[v].fail=root;

(t[v].s+=t[t[v].fail].s)%=mods;

q[++tail]=v;

} else t[fnow].r[i]=t[t[fnow].fail].r[i];

}}int getans(int a)}}

int res=0;

for(int i=0;i<=cnt;i++)

for(int h=0;h<=k;h++)

for(int p1=0;p1<2;p1++)

for(int p2=0;p2<2;p2++)

(res+=f[(a[0]&1)][i][h][p1][p2])%=mods;

return res;

}int main()

now=t[now].r[cd];

}scanf("%d",&cd);

(t[now].s+=cd)%=mods;

}buildfail();

printf("%d\n",((getans(dr)-getans(dl))%mods+mods)%mods);

return

0;}

NOIP2017提高組模擬賽4 (總結)

這道題就是很簡單的bfs,可以觀察到n變化到m是近似成倍增長的。其實從最小到最大的變化也就只有30次而已。include include include typedef long long ll using namespace std const int maxl 100 const int oo ...

NOIP2017提高組模擬賽5 (總結)

其實就是將乙個點f拆成向左l向右r的兩個點,然後將所有點排序 不用排序也行,直接找 選第乙個l,從後往前選第乙個不與l同乙個f的r。選最後乙個r,從前往後選第乙個不與r同乙個f的l。答案中的最大值即為兩點之間的最遠距離。證明如下 0 數學方法 把01看成a b個點。設s a b,x 最少要翻轉次數,...

NOIP2017提高組 模擬賽 26(總結)

題目描述 解題思路 構造法 假設現在有m個點,刪除乙個點,剩下的m 1個點都已經確定,那麼刪除的這個點應該染什麼顏色。假如這個點所在的行的點數為奇數,那麼點的染色只與它所在的列有關 若列有偶數個點,那麼這個點的顏色就可以確定了,哪種顏色少選哪種。否則隨便選 假如這個點所在的列的點數為奇數,與上面類似...