CF995E Number Clicker 解题报告

CF995E Number Clicker

题目描述

Allen is playing Number Clicker on his phone.

He starts with an integer u u on the screen. Every second, he can press one of 3 buttons.

Turn \(u \to u+1 \pmod{p}\).

Turn \(u \to u+p-1 \pmod{p}\).

Turn \(u \to u^{p-2} \pmod{p}\).

Allen wants to press at most 200 buttons and end up with v v on the screen. Help him!

输入输出格式

输入格式:

The first line of the input contains 3 positive integers: \(u, v, p\)( \(0 \le u, v \le p-1\) , \(3 \le p \le 10^9 + 9\) ). \(p\) is guaranteed to be prime.

输出格式:

On the first line, print a single integer \(\ell\) , the number of button presses.

On the second line, print integers \(c_1, \dots, c_\ell\), the button presses.

For \(1 \le i \le \ell\) , \(1 \le c_i \le 3\).

We can show that the answer always exists.


长见识了。

发现这道题可以建成一个比较随机的图。

根据生日攻击,我们基本上只需要图的点数\(p\)开根号个\(\sqrt p\),就可以找到答案了。

于是进行双向搜索,合并答案即可。


Code:

#include <cstdio>
#include <map>
#define ll long long
const int N=2e5;
ll u,v,p,q[N+10],l=1,r=0,s[N],tot;
std::map <ll,ll > pre,used,opt,pre0,opt0;
void in(ll now,ll to,ll op)
{
    if(!used[to])
    {
        used[to]=1;
        opt[to]=op;
        pre[to]=now;
        q[++r]=to;
    }
}
ll quickpow(ll d,ll k)
{
    ll f=1;
    while(k)
    {
        if(k&1) f=f*d%p;
        d=d*d%p;
        k>>=1;
    }
    return f;
}
int bfs0()
{
    q[++r]=u;
    while(l<=r&&r<=N)
    {
        ll now=q[l++];
        if(now==v)
        {
            while(now!=u) s[++tot]=opt[now],now=pre[now];
            printf("%lld\n",tot);
            for(int i=tot;i;i--)
                printf("%lld ",s[i]);
            return 1;
        }
        ll to=(now+1)%p;
        in(now,to,1);
        to=(now+p-1)%p;
        in(now,to,2);
        to=quickpow(now,p-2);
        in(now,to,3);
    }
    return 0;
}
void in0(ll now,ll to,ll op)
{
    if(!used[to])
    {
        used[to]=1;
        opt0[to]=op;
        pre0[to]=now;
        q[++r]=to;
    }
}
ll tmp;
void swap(ll &x,ll &y){tmp=x,x=y,y=tmp;}
void bfs1()
{
    used.clear();
    l=1,r=0;
    q[++r]=v;
    while(l<=r&&r<=N)
    {
        ll now=q[l++];
        if(pre.find(now)!=pre.end())
        {
            ll t=now;
            while(now!=u) s[++tot]=opt[now],now=pre[now];
            for(int i=1;i<=tot>>1;i++) swap(s[i],s[tot+1-i]);
            now=t;
            while(now!=v) s[++tot]=opt0[now],now=pre0[now];
            printf("%lld\n",tot);
            for(int i=1;i<=tot;i++)
                printf("%lld ",s[i]);
            return;
        }
        ll to=(now+1)%p;
        in0(now,to,2);
        to=(now+p-1)%p;
        in0(now,to,1);
        to=quickpow(now,p-2);
        in0(now,to,3);
    }
}
int main()
{
    //freopen("dew.out","w",stdout);
    scanf("%lld%lld%lld",&u,&v,&p);
    if(bfs0()) return 0;
    bfs1();
    return 0;
}

2018.10.9

转载于:https://www.cnblogs.com/butterflydew/p/9762632.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
from PyQt5.QtCore import QTimer from PyQt5.QtGui import QCursor from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton class MouseClicker(QWidget): def init(self): super().init() # 设置窗口标题 self.setWindowTitle("鼠标连点器") # 创建UI界面 self.label_count = QLabel("点击次数:") self.edit_count = QLineEdit() self.label_interval = QLabel("间隔时间(ms):") self.edit_interval = QLineEdit() self.btn_start = QPushButton("开始") # 设置布局 layout_count = QHBoxLayout() layout_count.addWidget(self.label_count) layout_count.addWidget(self.edit_count) layout_interval = QHBoxLayout() layout_interval.addWidget(self.label_interval) layout_interval.addWidget(self.edit_interval) layout_main = QVBoxLayout() layout_main.addLayout(layout_count) layout_main.addLayout(layout_interval) layout_main.addWidget(self.btn_start) self.setLayout(layout_main) # 连接按钮的点击事件 self.btn_start.clicked.connect(self.start_clicking) # 创建计时器 self.timer = QTimer() self.timer.timeout.connect(self.click) def start_clicking(self): # 获取点击次数和间隔时间 count = int(self.edit_count.text()) interval = int(self.edit_interval.text()) # 设置计时器的时间间隔 self.timer.setInterval(interval) # 开始计时器 self.timer.start() # 禁用开始按钮 self.btn_start.setEnabled(False) # 设置光标样式为等待 QApplication.setOverrideCursor(QCursor(QtCore.Qt.WaitCursor)) # 记录已经点击的次数 self.clicked_count = 0 def click(self): # 点击鼠标左键 QCursor().pos() QCursor().setPos(100, 100) QCursor().pos() QApplication.processEvents() # 增加已经点击的次数 self.clicked_count += 1 # 如果达到设定的点击次数,停止计时器并启用开始按钮 if self.clicked_count >= int(self.edit_count.text()): self.timer.stop() self.btn_start.setEnabled(True) # 设置光标样式为默认 QApplication.restoreOverrideCursor() if name == "main": app = QApplication([]) mouse_clicker = MouseClicker() mouse_clicker.show() app.exec_() 打包为可执行文件
05-15

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值