20190915杂题选讲

T1

设\(b_1=p_1^{a_1}p_2^{a_2}…p_n^{a_n}\),显然答案最大为\(\sum a_i\)

考虑让\(\sum a_i\)最大,那\(b_1\)不能有有超过5的质因子,因为\(2^2<5\)。3的个数最多也只有一个,因为\(2^3<3^2\)

于是就可以dp,设\(f[i][j][k]\)表示填到第i个数,gcd可以表示为\(2^j3^k\)的答案,分类讨论转移一下,最后答案为\(f[n][0][0]\)

code:

#include <bits/stdc++.h>
#define N 1000005
#define ll long long
#define il inline
#define For(i,x,y) for(int i=(x);i<=(y);++i)
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
#define mod 1000000007
using namespace std;
int f[N][20][2],n,_2[N],_3[N],lim2;

int main(){
    int n;
    scanf("%d",&n);_2[0]=1;
    int x=log2(n);
    For(i,1,x) _2[i]=_2[i-1]*2%mod;
    for(int bit=0,i=1;i<=n;i*=3,bit++) _3[bit]=i;
    f[1][x][0]=1;
    if((1<<(x-1))*3<=n) f[1][x-1][1]=1;
    For(i,2,n)
        Rof(j,x,0){
            Rof(k,(n>=3),0){
                if(_2[j]*_3[k]<=n){
                    (f[i][j][k]+=1ll*f[i-1][j][k]*max(0ll,1ll*n/(_2[j]*_3[k])-i+1)%mod)%=mod;
                    if(j>0) (f[i][j-1][k]+=1ll*f[i-1][j][k]*(1ll*n/(_2[j-1]*_3[k])-n/(_2[j]*_3[k]))%mod)%=mod;
                    if(k>0) (f[i][j][k-1]+=1ll*f[i-1][j][k]*(1ll*n/(_2[j]*_3[k-1])-n/(_2[j]*_3[k]))%mod)%=mod;
                }
            }
        }
    printf("%d\n",f[n][0][0]);
}

T2

先贴个代码,回家补题解

#include <bits/stdc++.h>
#define N 200005
#define ll long long
#define il inline
#define For(i,x,y) for(int i=(x);i<=(y);++i)
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
#define mid ((l+r)>>1)
#define lson t[o].ls,l,mid
#define rson t[o].rs,mid+1,r
#define bas rt,1,n
#define mod 998244353
using namespace std;

int cnt=0,rt=1,_=0;
ll _pow[N];
struct qwq{ int ls,rs;ll f,g,tf,tg,ans; } t[N<<2];

il void add(ll &x,ll y){ x+y>=mod?x=x+y-mod:x=x+y; }
il ll adD(ll x,ll y){ return x+y>=mod?x+y-mod:x+y; }
il ll mnS(ll x,ll y){ return x-y<0?x-y+mod:x-y; }
il void pushup(int o){ t[o].ans=adD(adD(t[t[o].ls].ans,t[t[o].rs].ans),t[o].f); }
void build(int &o,int l,int r){
    o=++cnt;
    t[o].f=t[o].ans=0;
    t[o].g=t[o].tf=t[o].tg=1;
    if(l==r) return;
    build(lson),build(rson);
    pushup(o);
}
il void pushdowntg(int o,int x){
    t[o].g=1ll*t[o].g*x%mod;
    t[o].tg=1ll*t[o].tg*x%mod;
}
il void pushdowntf(int o,int x){
    t[o].f=1ll*t[o].f*x%mod;
    t[o].tf=1ll*t[o].tf*x%mod;
    t[o].ans=1ll*t[o].ans*x%mod;
}
il void PushDown(int o){
    if(t[o].tf!=1) pushdowntf(t[o].ls,t[o].tf),pushdowntf(t[o].rs,t[o].tf),t[o].tf=1;
    if(t[o].tg!=1) pushdowntg(t[o].ls,t[o].tg),pushdowntg(t[o].rs,t[o].tg),t[o].tg=1;
}
void modify(int o,int l,int r,int L,int R){
    PushDown(o);
    int _l=t[o].ls,_r=t[o].rs;
    if(L==l && r==R){
        add(t[o].f,_pow[_]);
        pushdowntf(_l,2),pushdowntf(_r,2);
        pushup(o);
        return;
    }
    add(t[o].g,_pow[_]);
    if(R<=mid){
        modify(lson,L,R);
        PushDown(_r);
        add(t[_r].f,mnS(_pow[_],t[_r].g)),add(t[_r].g,t[_r].g);
        pushdowntf(t[_r].ls,2),pushdowntf(t[_r].rs,2);
        pushdowntg(t[_r].ls,2),pushdowntg(t[_r].rs,2);
        pushup(_r);
    } else if(L>mid){
        modify(rson,L,R);
        PushDown(_l);
        add(t[_l].f,mnS(_pow[_],t[_l].g)),add(t[_l].g,t[_l].g);
        pushdowntf(t[_l].ls,2),pushdowntf(t[_l].rs,2);
        pushdowntg(t[_l].ls,2),pushdowntg(t[_l].rs,2);
        pushup(_l);
    } else modify(lson,L,mid),modify(rson,mid+1,R);
    pushup(o);
}

int main(){
    int n,q,op,l,r;_pow[0]=1;
    scanf("%d%d",&n,&q);
    For(i,1,q) _pow[i]=(_pow[i-1]+_pow[i-1])%mod;
    build(bas);
    while(q--){
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d",&l,&r);
            modify(bas,l,r);
            _++;
        } else printf("%lld\n",t[rt].ans);
    }
} 

T3

设\(l=l-1\), \(L=\lfloor l/m \rfloor\), \(R=\lfloor r/m \rfloor\)

最后的式子可以化成\((pre[r]-k*R)-(pre[l]-k*L)-k*\lceil (r\%m-l\%m)/m \rceil\)

获得i对应的左端点时,处理一下i前出现的每个余数对应的最小值就行了

code:

#include <bits/stdc++.h>
#define N 1000005
#define ll long long
#define il inline
#define For(i,x,y) for(int i=(x);i<=(y);++i)
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
#define Edge(x) for(int i=head[x];i;i=e[i].nxt)
#define mod 1000000007
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define ls(x) t[x].ls,l,mid
#define rs(x) t[x].rs,mid+1,r
#define mset(x,y) memset(x,y,sizeof(x))
#define mcpy(x,y) memcpy(x,y,sizeof(x))
using namespace std;

ll pre[N],mn[11];

int main(){
    int n,m,k;
    ll ans=0;
    scanf("%d%d%d",&n,&m,&k);
    mset(mn,0x3f);mn[0]=0;
    For(i,1,n) scanf("%lld",&pre[i]),pre[i]+=pre[i-1];
    For(i,1,n) pre[i]-=1ll*k*(1ll*i/m);
    For(i,1,n){
        For(j,0,min(i-1,m-1))
            ans=max(pre[i]-mn[j]-k*((i%m-j+m-1)/m),ans);
        mn[i%m]=min(mn[i%m],pre[i]);
    }
    printf("%lld\n",ans);
} 

T4

题解咕了,放个代码:

#include <bits/stdc++.h>
#define N 5000005
#define ll long long
#define il inline
#define For(i,x,y) for(int i=(x);i<=(y);++i)
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
#define Edge(x) for(int i=head[x];i;i=e[i].nxt)
#define mod 19260817
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define ls(x) t[x].ls,l,mid
#define rs(x) t[x].rs,mid+1,r
#define mset(x,y) memset(x,y,sizeof(x))
#define mcpy(x,y) memcpy(x,y,sizeof(x))
using namespace std;
char s[N],t[N];
ll f[30],ans=1;
int main(){
    int n,m,cnt=0;
    scanf("%d%d\n%s\n%s",&n,&m,s+1,t+1);
    cnt=n;
    For(i,1,m){
        if(t[i]>='A' && t[i]<='Z'){
            ll tmp=f[t[i]-'A'];
            f[t[i]-'A']=ans;
            ans=(2ll*ans%mod-tmp+mod)%mod;
        } else{
            if(!cnt) continue;
            (ans+=1)%=mod;
            (f[s[cnt]-'A']+=1)%=mod;
            cnt--;
        }
    } printf("%lld\n",ans);
}

原文地址:https://www.cnblogs.com/PsychicBoom/p/11560138.html

时间: 2024-07-28 18:21:56

20190915杂题选讲的相关文章

正睿OI DAY3 杂题选讲

正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n\leq k^2\) 暴力 \(n\geq k^2\),找点x,求直线l经过x,且点数最多,点数\(\geq k+1\),递归,否则再找一个 One Point Nine Nine 现在平面上有\(n\)个点,已知有一个常数\(D\). 任意两点的距离要么\(\leq D\),要么\(\geq 1.

「总结」杂题选讲

Bitwise Xor 我们可以发现一个序列中的最小的异或值是两个大小相邻的数的\(xor\)取\(min\). 那么我们对序列排序. 只需要计算相邻的\(xor\)是大于等于\(k\)的方案. \(dp[i]\)是以\(i\)结尾最小\(xor\)大于\(K\)的方案. 然后我们可以类似于用树状数组来搞最长升降转移. 这次用\(trie\)来转移. MOD Problem 大水题 \[\begin{aligned} ans&=\sum\limits_{i=1}^{n}n\ mod\ I\&

洛谷 P1595 信封问题(周五杂题选讲)(错排公式)

题目描述 某人写了n封信和n个信封,如果所有的信都装错了信封.求所有信都装错信封共有多少种不同情况. 输入输出格式 输入格式: 一个信封数n(n<=20) 输出格式: 一个整数,代表有多少种情况. 题解 本题即为伯努利信封问题 360百科:错排公式 STD 1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 int b(int n) 5 { 6 if (n==1) return 0; 7 else if (n==2) r

5.30杂题选讲

前三题为水题,后面两题更有意思. 然而代码全都咕咕咕了,也许以后会补. Hdu1520 Anniversary party 简单树形DP. Hdu6386 Age of Moyu 简单最短路. bzoj3679 数字之积 简单数位DP. CF Gym 101482G Gathering 首先对于每个点,可行的区域显然是个矩形,那么可以先对这些矩形求交,得到合法区域. 如果不考虑限制,那么最优点显然是\(x,y\)的中位数. 考虑限制之后,只要定下\(x\),那么最优的\(y\)也是确定的. 而且

ZROI 19.08.02 杂题选讲

给出\(n\)个数,用最少的\(2^k\)或\(-2^{k}\),使得能拼出所有数,输出方案.\(n,|a_i|\leq 10^5\). 显然一个绝对值最多选一次.这个性质非常强. 如果所有都是偶数,可以直接除以\(2\). 否则\(1\)或\(-1\)必须选,暴力枚举选哪个然后递归,每层去重,发现最多只会递归\(\log a\)次.总复杂度\(O((n+a)\log n)\),等价于线段树上区间长度总和. \(n\)个数,每次可以花费\(1\)的代价给某个数\(+1\)或\(-1\),问变成不

【最小生成树杂题】

这里谈一下最小生成树 生成树的概念:连通图G的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G的生成树.生成树是连通图的极小连通子图.所谓极小是指:若在树中任意增加一条边,则将出现一个回路:若去掉一条边,将会使之变成非连通图. 生成树各边的权值总和称为生成树的权.权最小的生成树称为最小生成树. 最小生成树一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.常用于求最小生成树得算法包括kruskal(克鲁斯卡尔)算法或Prim(

[杂题]URAL1822. Hugo II&#39;s War

看懂题意的请直接跳过下一坨! 本人有表达障碍! ========================================== 题意: (题意真的很难很难懂啊!!!  去他娘的**) 有一个王国,王国里有一个国王(编号为1),他有(编号为2~n) n-1个臣子(这些臣子并不全和他有直接关系) 然后呢 国王要去打架,但是只有当他的x%个及以上的直系下属(与他有直接关系的臣子)做好打架的准备了,他才能去打架 他的直系下属也有下属,也要其中x%及以上的下属做好打架准备了,那些直系下属才会开始准备

_杂题_

杂题集 是个放题的好地方! **** 5.28 **** - BZOJ [3052] 糖果公园 - 据说是一道区间操作的综合题,但现在貌似蹦了? 现在还是太水,之后再来写吧. *************

hdu 3641 数论 二分求符合条件的最小值数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=3641 学到: 1.二分求符合条件的最小值 /*==================================================== 二分查找符合条件的最小值 ======================================================*/ ll solve() { __int64 low = 0, high = INF, mid ; while(low <=