UOJ73 【WC2015】未来程序
题目描述:给出输入和暴力程序,求输出。共10个测试点。
测试点1:
输入\(a,b,c\),求\(a\times b \ \mathrm{mod} \ c\)
\(a,b,c\)属于long long
范围。
使用龟速乘或者快速乘。
#include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef long long LL;
LL a, b, mod;
inline void upd(LL &a, LL b){a += b; if(a >= mod) a -= mod;}
inline LL mul(LL a, LL b){
LL res = 0;
while(b){
if(b & 1) upd(res, a);
upd(a, a); b >>= 1;
}
return res;
}
int main(){
freopen("program1.in", "r", stdin);
freopen("program1.out", "w", stdout);
for(Rint i = 1;i <= 10;i ++){
scanf("%lld%lld%lld", &a, &b, &mod); a %= mod; b %= mod;
printf("%lld\n", mul(a, b));
}
}
测试点2:发现它就是个线性递推,暴力矩阵快速幂即可。
#include<bits/stdc++.h>
#define Rint register int
#define int unsigned
using namespace std;
typedef long long LL;
const int N = 3;
LL n;
int mod;
inline void upd(int &a, int b){a += b; if(a >= mod) a -= mod;}
inline int add(int a, int b){return (a + b >= mod) ? (a + b - mod) : (a + b);}
inline int sub(int a, int b){return (a < b) ? (a + mod - b) : (a - b);}
struct Matrix {
int a[N][N];
inline Matrix(){memset(a, 0, sizeof a);}
inline Matrix operator * (const Matrix &o) const {
Matrix res;
for(Rint i = 0;i < N;i ++)
for(Rint k = 0;k < N;k ++)
for(Rint j = 0;j < N;j ++)
upd(res.a[i][j], (LL) a[i][k] * o.a[k][j] % mod);
return res;
}
} A, B, C;
inline Matrix kasumi(Matrix A, LL n){
Matrix res;
for(Rint i = 0;i < N;i ++) res.a[i][i] = 1;
while(n){
if(n & 1) res = res * A;
A = A * A; n >>= 1;
}
return res;
}
signed main(){
freopen("program2.in", "r", stdin);
freopen("program2.out","w",stdout);
A.a[0][0] = A.a[0][2] = A.a[1][0] = A.a[1][1] = A.a[2][0] = B.a[0][0] = 1; A.a[0][1] = 2;
for(Rint i = 1;i <= 10;i ++){
cin >> n >> mod;
C = kasumi(A, n) * B;
cout << add(sub(C.a[0][0], C.a[1][0]), sub(C.a[2][0], C.a[1][0])) << endl;
}
}
测试点3:
输入\(n=10^{15}\),求\(\sum_{i=1}^ni^k \ \mathrm{mod} \ 2^{64}(k=0,1,2,3,4)\)
\sum_{i=1}^ni^0&=n \\
\sum_{i=1}^ni^1&=\frac{n(n+1)}{2} \\
\sum_{i=1}^ni^2&=\frac{n(n+1)(2n+1)}{6} \\
\sum_{i=1}^ni^3&=(\frac{n(n+1)}{2})^2 \\
\sum_{i=1}^ni^4&=\frac{n(n+1)(2n+1)(3n^2-3n+1)}{30}
\end{aligned}
\]
首先用__int128
求出\(\frac{n(n+1)}{2}\),然后求出\(\frac{1}{3}\)和\(\frac{1}{15}\),直接计算。
#include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef unsigned long long LL;
typedef __int128 LLL;
LL n, m;
inline LL kasumi(LL a, LL b){
LL res = 1;
while(b){
if(b & 1) res *= a; a *= a; b >>= 1;
}
return res;
}
LL inv3 = kasumi(3, (1ull << 63) - 1);
LL inv15 = kasumi(15, (1ull << 63) - 1);
int main(){
scanf("%llu", &n); m = (LLL) n * (n + 1) / 2;
printf("%llu\n", n); printf("%llu\n", n);
printf("%llu\n", m); printf("%llu\n", m);
printf("%llu\n", m * (2 * n + 1) * inv3); printf("%llu\n", m * (2 * n + 1) * inv3);
printf("%llu\n", m * m); printf("%llu\n", m * m);
printf("%llu\n", m * (2 * n + 1) * (3 * n * n + 3 * n - 1) * inv15);
printf("%llu\n", m * (2 * n + 1) * (3 * n * n + 3 * n - 1) * inv15);
}
测试点4:
输入\(n\times m\)的随机01矩阵,有两个问题:
求\(1\)的个数\(ans\),输出\(\frac{ans(ans-1)}{2}\)
对于每个\(1\),求离它最近的\(0\)的距离之和(曼哈顿距离)
\(1\le n,m\le 1000\)
看上面的粗体字。
#include <iostream>
const int N = 5000, inf = 0x3F3F3F3F;
int n, m, type;
bool data[N + 11][N + 11];
int seed;
int next_rand(){
static const int P = 1000000007, Q = 83978833, R = 8523467;
return seed = ((long long)Q * seed % P * seed + R) % P;
}
void generate_input(){
std::cin >> n >> m >> type;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
data[i][j] = bool((next_rand() % 8) > 0);
}
long long count1(){
long long ans = 0LL;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
if(data[i][j]) ++ ans;
return ans * (ans - 1);
}
int abs_int(int x){
return x < 0 ? -x : x;
}
inline int max(int a, int b){return a > b ? a : b;}
long long count2(){
long long ans = 0LL;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
if(data[i][j])
for(int k = 1;k <= n + m - 2;k ++){
bool flag = false;
for(int x = max(i - k, 0); x <= i + k && x < n && !flag; x ++){
int y = j - (k - abs(i - x));
if(y >= 0 && y < m && !data[x][y]) flag = true;
y = j + (k - abs(i - x));
if(y >= 0 && y < m && !data[x][y]) flag = true;
}
if(flag){ans += k; break;}
}
return ans;
}
int main(){
freopen("program4.in", "r", stdin);
freopen("program4.out", "w", stdout);
std::cin >> seed;
for(int i = 0; i < 10; i++){
generate_input();
std::cout << (type == 1 ? count2() : count1()) << std::endl;
}
return 0;
}
测试点5:
输入\(n\times m\)的随机01矩阵,求有多少个全1子矩阵。
\(1\le n,m\le 5000\)
是不是觉得很熟悉?
#include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef long long LL;
const int N = 5003;
int seed;
int next_rand(){
static const int P = 1000000007, Q = 83978833, R = 8523467;
return seed = ((long long)Q * seed % P * seed + R) % P;
}
int n, a[N][N], pre[N][N], stk[N], top;
LL ans1;
int main(){
freopen("program5.in", "r", stdin);
freopen("program5.out", "w", stdout);
scanf("%d", &seed);
for(Rint T = 1;T <= 10;T ++){ ans1 = 0;
scanf("%d", &n); scanf("%d", &n);
for(Rint i = 1;i <= n;i ++)
for(Rint j = 1;j <= n;j ++)
a[i][j] = next_rand() & 7;
for(Rint i = 1;i <= n;i ++)
for(Rint j = 1;j <= n;j ++)
if(a[i][j]) pre[i][j] = pre[i - 1][j] + 1;
else pre[i][j] = 0;
for(Rint i = 1;i <= n;i ++){
LL ans = 0; top = 0;
for(Rint j = 1;j <= n;j ++){
ans += pre[i][j];
while(top && pre[i][j] <= pre[i][stk[top]]){
ans -= (LL) (pre[i][stk[top]] - pre[i][j]) * (stk[top] - stk[top - 1]);
-- top;
}
stk[++ top] = j;
ans1 += ans;
}
}
printf("%lld\n", ans1);
}
}
测试点6:
输入\(n,a,b,c\),设\(f_0=0,f_n=(af_{n-1}^2+b) \ \mathrm{mod} \ 2^{64} \ \mathrm{mod} \ c\),求\(f_n\)
\(n,a,b,c\)在long long
范围内。
有个东西叫做floyd判圈算法。这个算法可以在线性时间复杂度内计算自动机/迭代函数/链表(每个点只有一条出边的有向图)上面的环。
直接讲做法了:首先从\(S\)出发,然后设两个指针\(x,y\),一个快指针和一个慢指针,快指针每次走\(2\)步,慢指针每次走\(1\)步,然后它们在\(M\)点相遇。
计算环长:令其中一个指针一直走,记录步数。
计算环起点:令其中一个指针在\(M\),另一个在\(S\),然后以同样的速度走。
然而如果你跑这东西的话会耗死你。【我都写完上面的东西了它一个数据点都没跑出来】
需要用一个Brent判环算法。这东西的过程是这样的。
首先定义一个步长\(step=2\),当前步数\(cnt\),一个![img](file:///C:\Users\86158\AppData\Local\Temp\SGPicFaceTpBq\4356\1BE49467.png)指针\(x\)和一个![img](file:///C:\Users\86158\AppData\Local\Temp\SGPicFaceTpBq\4356\1BDDB9F2.png)指针\(y\)。
- 让\(x\)一直跑,遇到\(y\)的时候退出,\(cnt\)环长。
- 否则让\(step=step\times 2,y=x,cnt=0\)
知道环长之后,令\(x=y=0\),然后让\(x\)跑\(cnt\)遍,然后再让\(x,y\)一起跑,相遇的地方就是环起点。
然后从环起点开始跑就可以了。
#include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef unsigned long long LL;
const LL N = 1e10;
LL n, a, b, c;
inline LL nxt(LL x){return (x * x * a + b) % c;}
int main(){
freopen("program6.in", "r", stdin);
freopen("program6.out", "w", stdout);
for(Rint T = 1;T <= 10;T ++){
scanf("%llu%llu%llu%llu", &n, &a, &b, &c);
LL s = 0, r = 2, x = 0, y = 0, cnt = 0;
while(true){
y = nxt(y); ++ s;
if(x == y) break;
if(s == r){x = y; s = 0; r <<= 1;}
}
x = y = 0;
while(cnt < s) x = nxt(x), ++ cnt;
cnt = 1;
while(x != y) x = nxt(x), y = nxt(y), ++ cnt;
r = (n - cnt) % s + 1;
while(r --) x = nxt(x);
printf("%llu\n", x);
}
}
测试点7:
\(16*16\)的数独。
是不是觉得很熟悉?
#include<cstdio>
#include<cstring>
#define Rint register int
using namespace std;
const int N = 1000003, n = 4096, m = 1024;
int a[17][17], r[N], u[N], l[N], d[N], s[N], col[N], row[N], h[N], ans[N], cnt;
inline void init(){
for(Rint i = 0;i <= m;i ++){
l[i] = i - 1; r[i] = i + 1;
u[i] = d[i] = i;
}
l[0] = m; r[m] = 0;
memset(h, -1, sizeof h);
memset(s, 0, sizeof s);
memset(col, 0, sizeof col);
memset(row, 0, sizeof row);
memset(ans, 0, sizeof ans);
cnt = m + 1;
}
inline void insert(int x, int y){
s[y] ++; row[cnt] = x; col[cnt] = y;
u[cnt] = y; d[cnt] = d[y];
d[y] = u[d[y]] = cnt;
if(h[x] < 0) h[x] = l[cnt] = r[cnt] = cnt;
else {
r[cnt] = h[x];
l[cnt] = l[h[x]];
l[h[x]] = r[l[h[x]]] = cnt;
}
++ cnt;
}
inline void remove(int y){
r[l[y]] = r[y]; l[r[y]] = l[y];
for(Rint i = d[y];i != y;i = d[i])
for(Rint j = r[i];j != i;j = r[j]){
u[d[j]] = u[j];
d[u[j]] = d[j];
s[col[j]] --;
}
}
inline void resume(int y){
for(Rint i = u[y];i != y;i = u[i])
for(Rint j = l[i];j != i;j = l[j]){
u[d[j]] = d[u[j]] = j;
s[col[j]] ++;
}
r[l[y]] = l[r[y]] = y;
}
inline bool dance(int dep){
if(!r[0]){
for(Rint i = 0;i < dep;i ++){
int x = (ans[i] - 1) / 256 + 1, y = (ans[i] - 1) / 16 % 16 + 1, z = (ans[i] - 1) % 16 + 1;
a[x][y] = z;
}
return true;
}
int c = r[0];
for(Rint i = r[0];i;i = r[i]) if(s[i] < s[c]) c = i;
remove(c);
for(Rint i = d[c];i != c;i = d[i]){
ans[dep] = row[i];
for(Rint j = r[i];j != i;j = r[j]) remove(col[j]);
if(dance(dep + 1)) return true;
for(Rint j = l[i];j != i;j = l[j]) resume(col[j]);
}
resume(c);
return false;
}
int main(){
freopen("program7.in", "r", stdin);
freopen("program7.out", "w", stdout);
for(Rint k = 1;k <= 4;k ++){
init();
for(Rint i = 1;i <= 16;i ++)
for(Rint j = 1;j <= 16;j ++){
int x;
while(((x = getchar()) < 'A' || x > 'P') && x != '?');
a[i][j] = (x == '?') ? 0 : x - 'A' + 1;
for(Rint k = 1;k <= 16;k ++)
if(a[i][j] == k || !a[i][j]){
int id = ((i - 1) * 16 + j - 1) * 16 + k;
int c1 = (i - 1) * 16 + j, c2 = 256 + (i - 1) * 16 + k, c3 = 512 + (j - 1) * 16 + k,
c4 = 768 + ((i - 1) / 4 * 4 + (j - 1) / 4) * 16 + k;
insert(id, c1); insert(id, c2); insert(id, c3); insert(id, c4);
}
}
dance(0);
for(Rint l = 0;l < k;l ++){
for(Rint i = 1;i <= 16;i ++)
for(Rint j = 1;j <= 16;j ++)
printf("%c", a[i][j] + 'A' - 1);
putchar('\n');
}
}
}
测试点8,9,10:咕了
UOJ73 【WC2015】未来程序的更多相关文章
- 【洛谷4920】[WC2015] 未来程序(提答题)
点此看题面 大致题意: 把\(10\)个点的暴力代码和输入数据都给你,让你求出输出数据. 子任务\(1\) 第一个子任务自然是拿来送分用的... 容易发现就是一个快速乘的过程啊. 代码如下: #inc ...
- [WC2015]未来程序(提交答案)
sub1:ans=a*b%c,龟速乘即可. #include <stdio.h> #include <stdlib.h> unsigned long long a, b, c, ...
- uoj#73 【WC2015】未来程序
在 2047 年,第 64 届全国青少年信息学奥林匹克冬令营前夕,B君找到了 2015 年,第 32 届冬令营的题目来练习. 他打开了第三题 “未来程序” 这道题目: 本题是一道提交答案题,一共 10 ...
- 如何A掉未来程序改
话说有这样一道神题:[集训队互测2015]未来程序·改. 大意是要求写一个简单的C++解释器!这里去掉了C++的许多特性,连简单的break和continue都没有了! 话说NOI被屠了之后,一时心血 ...
- Uoj 73 未来程序
Uoj 73 未来程序 神仙提答. Subtask 1 仔细阅读,发现是要计算 \(a*b\ \%\ c\).用龟速乘或者 \(python\) 直接算. Subtask 2 仔细阅读并手算一下,发现 ...
- UOJ#73. 【WC2015】未来程序 提交答案题
原文链接www.cnblogs.com/zhouzhendong/p/UOJ73.html 前言 纯属理性愉悦. 题解 Subtask1 发现就是求 $a \times b \mod c $ . 写个 ...
- uoj98未来程序改 纯暴力不要想了
暴力模拟A了,数据还是良(shui)心(shui)的 90分的地方卡了半天最后发现一个局部变量被我手抖写到全局去了,,, 心碎*∞ 没什么好解释的,其实只要写完表达式求值(带函数和变量的),然后处理一 ...
- bzoj4020: 未来程序·改
只需写一个解释器 第一次预处理将输入进行分词,分割出 关键字,运算符,变量/函数名,整数常量,并对变量/函数名离散化以便处理 第二次预处理建语法树,每个节点存节点类型,变量定义表等信息 运行时在语法树 ...
- WC2015 题解
K小割 题目链接:WC2015 K小割 Description 题目很清楚了,已经不能说的更简洁了-- Solution 这道题出题人挺毒的,你需要针对不同的部分分施用不同的做法 . 第\(1\)部分 ...
随机推荐
- ConsoleLoggerExtensions.AddConsole(ILoggerFactory)已过时代码修复
0x00.问题 netcoreapp2.2环境下, Startup.cs 代码配置如下 public void Configure(IApplicationBuilder app, IHostingE ...
- 阿里企业邮箱smtp设置
阿里的邮箱没有SMTP授权码信息 SMTP服务器:smtp.mxhichina.com
- 二叉树、B树、B+树、B*树、VAL树、红黑树
二叉搜索树 每个节点只存储一个关键字, 每个节点最多有两个子节点, 左子节点存储的关键字小于本节点存储的关键字 右子节点存储的关键字大于本节点存储的关键字 搜索时,从根节点开始搜索,小于走左结点,大于 ...
- RAS非对称加密
加解密密钥不一致,一般私钥不公开,使用公钥加密,私钥解密,使用私钥加密,公钥可以解密. java代码 import javax.crypto.Cipher; import java.security. ...
- MonoSymbolFileException in CheckLineNumberTable
Mono.CompilerServices.SymbolWriter.MonoSymbolFileException: Exception of type 'Mono.CompilerServices ...
- 聊聊GIS中的坐标系|再版
本文约6500字,建议阅读时间15分钟. 作者:博客园/B站/知乎/csdn/小专栏 @秋意正寒 版权:转载请告知,并在转载文上附上转载声明与原文链接(https://www.cnblogs.com/ ...
- Node学习之(第三章:仿Apache显示目录列表的功能)
前言 今天咱们用Node.js中的核心模块以及上节学习的模板引擎art-template来实现服务器软件Apache的大体功能.用过Apache的朋友都知道,我们只需把本地文件放置在Apache的ww ...
- Linux记录history命令
对后面的(1)方法的提取文件改写法(强烈推荐) 记录存储位置: mkdir -p /usr/local/records chmod 777 /usr/local/records/chmod +t /u ...
- 【Linux下Hadoop-eclipse-plus-3.2.0】编译Hadoop连接eclipse的插件遇见的一系列错误,崩溃的操作
2019-09-02 23:35:22 前言:首先,我想吐槽下自己,居然花费了4到5个夜晚和中午的时间来做这件事情,直到刚才才顺利解决,我也挺佩服自己的! 我在这个过程中参考其他人的博客,非常感谢他们 ...
- Android笔记(五十九)Android总结:四大组件——Service篇
什么是服务? 服务(service)是Android中实现程序后台运行的解决方案,适用于去执行那些不需要和用户交互并且还需要长期运行的任务.服务的运行不依赖于任何用户界面. 服务运行在主线程中,所以在 ...