CQOI2016滚粗记

day0
上去试机发现鼠标是坏的,旁边是巴蜀的大牛和教师机…
随手敲了一个树剖和Pollard_rho,顺路用批处理对拍了一下,然后想去交一发意外的发现竟然木有网….

晚上复习了一下板子…然后写得有点兴奋了就睡不着辣…

day1
上歌乐山的时候还在下雨…
然后我7点就悠悠的到了门口…然后就在外面晃荡了40多分钟…
8点过就进了考场,发现解压密码一点都不好玩…

看到T1的时候心里一阵窃喜,嘿嘿我做过bzoj2229的,不就是一道分治最小割的水题吗…30分钟敲完就写了一个对拍,拍了一个小时木有错就默默的水过辣…

#include <iostream>
#include <cstdio>
#include <algorithm>
#define MAXN 855
#define MAXM 20005
#define inf 0x3f3f3f3f
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;

struct node
{
    int v, w, next;
}edge[MAXM];
int adj[MAXN], pos, n, m, a[MAXN], tmp[MAXN], T, S;
int d[MAXN], vd[MAXN], road[MAXN*MAXN], cnt;

inline void add(int u,int v,int w)
{
    edge[pos].v=v, edge[pos].w=w, edge[pos].next=adj[u];
    adj[u]=pos;
    ++pos;
    edge[pos].v=u, edge[pos].w=w, edge[pos].next=adj[v];
    adj[v]=pos;
    ++pos;
}

int aug(int u,int augco)
{
    if(u==T)return augco;
    int augc=augco, mind=n, delta, v;
    for(int p=adj[u];~p;p=edge[p].next)
        if(edge[p].w>0)
        {
            v=edge[p].v;
            if(d[v]+1==d[u])
            {
                delta=aug(v,min(augc,edge[p].w));
                edge[p].w-=delta, augc-=delta, edge[p^1].w+=delta;
                if(!augc||d[S]>=n)return augco-augc;
            }
            mind=min(mind,d[v]);
        }
    if(augco==augc)
    {
        if(!--vd[d[u]])d[S]=n;
        else ++vd[d[u]=mind+1];
    }
    return augco-augc;
}

int q[MAXM], head, tail;
bool vis[MAXN], in[MAXN];
void bfs()
{
    head=tail=0;
    q[++tail]=T, d[T]=0;
    int u, v;
    while(head<tail)
    {
        u=q[++head], in[u]=0;
        for(int p=adj[u];~p;p=edge[p].next)
            if(edge[p^1].w>0&&d[v=edge[p].v]>d[u]+1)
            {
                d[v]=d[u]+1;
                if(!in[v])q[++tail]=v, in[v]=1;
            }
    }
}

int isap()
{
    for(int p=0;p<pos;p+=2)
        edge[p].w=edge[p^1].w=(edge[p].w+edge[p^1].w)/2;
    for(int i=1;i<=n;++i)d[i]=inf, vd[i]=0, vis[i]=0;
    bfs();
    for(int i=1;i<=n;++i)
        if(d[i]!=inf)++vd[d[i]];
    int ans=0;
    while(d[S]<n)
        ans+=aug(S,inf);
    return ans;
}

void dfs(int u)
{
    vis[u]=1;
    for(int p=adj[u], v;~p;p=edge[p].next)
        if(edge[p].w>0&&!vis[v=edge[p].v])
            dfs(v);
}

void solve(int l,int r)
{
    if(l==r)return;
    S=a[l], T=a[r];
    int ans=isap();
    road[++cnt]=ans;
    dfs(S);
    int p1=l, p2=r;
    for(int i=l;i<=r;++i)
        if(vis[a[i]])tmp[p1++]=a[i];
        else tmp[p2--]=a[i];
    for(int i=l;i<=r;++i)
        a[i]=tmp[i];
    solve(l,p1-1), solve(p2+1,r);
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)adj[i]=-1, a[i]=i;
    int u, v, w;
    while(m--)
    {
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    solve(1,n);
    sort(road+1,road+cnt+1);
    int ans=1;
    for(int i=2;i<=cnt;++i)
        if(road[i]!=road[i-1])++ans;
    printf("%d\n",ans);
    return 0;
}

T2 不会的说…就默默滴写了个大暴力…外加一个分治乱写一共骗了40分…
附上之后写的题解… 题解链接

T3 一眼看穿是一个数位DP,然后…我TM搞了两个多小时都木有搞出来,真是太垃圾辣…

day1就这样160滚粗辣…
晚上就默默滴敲了几个计算几何和数学的板子…

day2
早上继续雨蒙蒙…
怀着对滚粗的美好向往,我默默滴进入机房…
然后…

T1 TM不就是想考Pollard_rho吗…不虚…
30分钟敲完,又写了一个对拍,没问题…
恩,100分稳稳滴…

#include <iostream>
#include <cstdio>
#include <algorithm>
#define abs(a) ((a)>0?(a):-(a))
#define LL long long int
using namespace std;

LL mul(LL a,LL pos,LL mod)
{
    LL ans=0;
    for(;pos;pos>>=1)
    {
        if(pos&1){ans+=a;if(ans>=mod)ans-=mod;}
        a+=a;if(a>=mod)a-=mod;
    }
    return ans;
}

LL power(LL a,LL pos,LL mod)
{
    LL ans=1;
    for(;pos;pos>>=1, a=mul(a,a,mod))
        if(pos&1)ans=mul(ans,a,mod);
    return ans;
}

bool Miller_Rabin(LL n)
{
    if(n==2||n==3)return 1;
    if(!(n&1))return 0;
    LL m=n-1, a, tmp, ans;
    int cnt=0;
    while(!(m&1))m>>=1, ++cnt;

    for(int i=0;i<20;++i)
    {
        a=rand()%(n-1)+1;
        tmp=power(a,m,n);
        for(int j=0;j<cnt;++j)
        {
            ans=mul(tmp,tmp,n);
            if(ans==1)
            {
                if(tmp!=1&&tmp!=n-1)return 0;
                break;
            }
            tmp=ans;
        }
        if(ans!=1)return 0;
    }
    return 1;
}

LL gcd(LL a,LL b)
{
    if(!b)return a;
    return gcd(b,a%b);
}

LL work(LL a,LL b)
{
    LL cnt=0, k=2, x0=rand()%a, y=x0, d;
    while(1)
    {
        ++cnt;
        x0=(mul(x0,x0,a)+b)%a;
        d=gcd(abs(y-x0),a);
        if(d!=1&&d!=a)return d;
        if(y==x0)return a;
        if(cnt==k)k+=k, y=x0;
    }
}

LL fac[105];
int tot;
void dfs(LL n)
{
    if(Miller_Rabin(n)){fac[++tot]=n;return;}
    LL p=n;
    while(p>=n)p=work(p,rand()%(n-1)+1);
    dfs(p), dfs(n/p);
}

void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{
    if(!b)d=a, x=1, y=0;
    else
    {
        exgcd(b,a%b,d,y,x);
        y-=a/b*x;
    }
}

LL ask_ni(LL a,LL b)
{
    LL d, x, y;
    exgcd(a,b,d,x,y);
    LL mod=b/d;
    return (x%mod+mod)%mod;
}

LL e, N, c;
int main()
{
    cin>>e>>N>>c;
    dfs(N);
    LL r=(fac[1]-1)*(fac[2]-1);
    LL d=ask_ni(e,r);
    cout<<d<<' '<<power(c,d,N);
    return 0;
}

T2 一开始木有看懂题啊…
然后磨了半个小时,然后加了一点补充说明就看懂了。
不就是一个水水的01Trie吗,不虚200稳稳滴…

#include <iostream>
#include <cstdio>
#include <algorithm>
#define MAXN 1000005
#define MAXM 15050000
using namespace std;

char w;
inline void GET(int &t)
{
    t=0;
    do w=getchar();while(w<'0'||w>'9');
    do{t=t*10+w-'0';w=getchar();}while(w>='0'&&w<='9');
}

int tmp[MAXN], temp, len[MAXN];

struct Trie
{
    int ch[MAXM][2], pos, id[MAXM];
    inline void insert(char w[],int len,int d)
    {
        int p=0;
        for(int i=1;i<=len;++i)
            if(!ch[p][w[i]])p=ch[p][w[i]]=++pos;
            else p=ch[p][w[i]];
        if(!id[p])id[p]=d;
    }
    inline void query(char w[])
    {
        int p=0;
        for(int i=1;i<33;++i)
        {
            if(ch[p][w[i]])p=ch[p][w[i]];
            else return;
            if(id[p])tmp[++temp]=id[p];
        }
    }
}t;

char s[36];

int main()
{
    int n, u, a, b, cnt=0, ans, mv, tot;
    char ask[10];
    GET(n);
    while(n--)
    {
        scanf("%s",ask);
        if(ask[0]=='A')
        {
            ++cnt, tot=0;
            for(int i=1;i<5;++i)
            {
                GET(u);
                for(int j=7;~j;--j)
                    if(u&(1<<j))s[++tot]=1;
                    else s[++tot]=0;
            }
            GET(len[cnt]);
            t.insert(s,len[cnt],cnt);
        }
        else
        {
            tot=0;
            for(int i=1;i<5;++i)
            {
                GET(u);
                for(int j=7;~j;--j)
                    if(u&(1<<j))s[++tot]=1;
                    else s[++tot]=0;
            }
            temp=0, t.query(s);
            sort(tmp+1,tmp+temp+1);
            GET(a), GET(b), ans=mv=0;
            for(int i=1;i<=temp;++i)
                if(mv<len[tmp[i]])
                {
                    mv=len[tmp[i]];
                    if(tmp[i]>b)break;
                    if(a<=tmp[i])++ans;
                }
            printf("%d\n",ans);
        }
    }
    return 0;
}

T3 一看,(⊙v⊙)嗯好像是一道赤裸裸数学题,然后就默默滴推了2个多小时,然后木有推出来,然后就写了一个大暴力,弃疗…

正解:大力出奇迹…我真是…

把128内的质数打出来,随便搞搞这个搞出来这个质数最多能被选多少次,然后枚举一个要选择的最大的质数,这样就可以枚举这个质数被选次数内的比这个质数小的所有质数了。就是个集合的无序拆分。
剪枝:10^14的第800000个伪光滑数一定比10^15的第800000个伪光滑数小,这样假设我们知道10^14的第800000个伪光滑数,这个数可以拿来剪枝,然后10^15的第800000个伪光滑数算起来就很快了,可以拿去剪10^16的第800000个伪光滑数。
by quack…
我就%%%%%%

day2 230彻底滚粗…

加上noip成绩默默滴排到了第8左右…
幸好noip考得好…
然后女生保护政策就默默滴拿了一个A类…
感觉不是很爽,毕竟D1T2出题人面向巴蜀选手出数据,居然让旋转卡壳和三分就这样水过辣,表示很不爽…
SB出题人!!!SB出题人!!!SB出题人!!!
重要的事情说三遍…

根据引用所述,交错序列是一个仅由0和1构成的序列,其中没有相邻的1(可以有相邻的0)。特征值定义为x^ay^b,其中x和y分别表示0和1出现的次数。长度为n的交错序列可能有多个。问题要求计算所有长度为n的交错序列特征值的和除以m的余数。 根据引用所述,输入文件包含一个行,该行包含三个整数n、a、b和m。其中,1≤n≤10000000,0≤a、b≤45,m<100000000。 为了解决这个问题,可以使用动态规划和矩阵快速幂优化的方法,具体实现可以参考引用提到的相关算法。算法的思路是通过计算长度为n的交错序列的特征值,然后将所有特征值求和并对m取余数。 具体步骤如下: 1. 使用动态规划计算长度为n的所有交错序列的特征值,将结果保存在一个矩阵中。 2. 使用矩阵快速幂优化,将动态规划的过程进行优化。 3. 对优化后的结果进行求和,并对m取余数。 4. 输出结果。 参考引用给出的博客中的代码实现,可以帮助你更好地理解和实现该算法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [BZOJ5298 CQOI2018 交错序列 【DP+矩阵快速幂优化】*](https://blog.csdn.net/weixin_30892987/article/details/99470493)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值