[UOJ73【WC2015】未来程序] 毒瘤提交答案题
第一次做提交答案题,感受到毒瘤出题人满满的恶意(考场上考这个原地爆炸)
然后中间会有一些奇奇怪怪的东西,写出他不那么暴力的代码之后,用输入跑出这些读入之后提交读出.
太毒瘤了,显然不是准备你考场上做完的,如果遇到了,就尽可能把简单好写,容易看出题意的点写了,不然时间上完全耗不起.
真开心
我们发现在第二个测试点里面有一个英语词典
问题:
1.第一年NOI是哪年?4位数字。1984
2.在这一行,答案是最常见6位的密码。123456
3.在这一行你需要输出一个人名,他的照片在这个文件的开头。
一个字符画:陈立杰 orzorzorz
4.在这一行,答案是3个可见符号。 $_$
真CCF
5.后面是一句名言(若干个单词),开始几个可以爆搜出来(以上问题也都可以爆搜出来)。如果历史学得好,你会发现这是《独立宣言》里的一句话woc woc woc woc ,最后一个爆搜不出来了,但是如果你做了T10,会发现里面有一份独立宣言orz orz orz orz,可以拿下来
综上,本题是出题人在嘿嘿嘿。
#73. 【WC2015】未来程序
在 2047 年,第 64 届全国青少年信息学奥林匹克冬令营前夕,B君找到了 2015 年,第 32 届冬令营的题目来练习。 他打开了第三题 “未来程序” 这道题目: 本题是一道提交答案题,一共 10 个测试点。 对于每个测试点,你会得到一段程序的源代码和这段程序的输入。你要运行这个程序,并保存这个程序的输出。 遗憾的是这些程序都效率极其地下,无法在比赛的 5 个小时内得到输出。 B君想了一下,决定用 2047 年的计算机来试着运行这个题目,他找到了 2015 年的编译器,并很快得到了结果…… 这时B君从梦中惊醒,发现自己居然在第 32 届冬令营赛场上。之前的一切只是南柯一梦,而自己正需要解决“未来程序”这道题目。 然而B君已经记不清梦中的程序运行的结果了,他试图再次运行这些程序。但是他发现计算机性能比梦里的差多了,程序确实都无法在 55 小时内得到结果。 他需要你的帮助,来得到那些梦中的结果。 本题是一道提交答案题,一共有 10 个测试点。 对于每个测试点,你会得到一段程序的源代码和这段程序的输入。你要运行这个程序,并保存这个程序的输出。 遗憾的是这些程序效率都极其低下,无法在比赛的 55 小时内得到输出。 你需要帮助B君得到这些程序的输出。题意
简单来说,10个点,给你10个c++暴力程序和10个输入,然后让你看懂这些代码在干什么事情t1
long long 范围a*b%p 考虑到linux直接上python.龟速乘+卡速米似乎也可以.t2
就是给你a,b,c,然后b=a+b,a=2b-a+c,c=2b-a+c,求n次这样运算之后最后a-2*b+c结果 裸上矩乘.#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define int long long
using namespace std;
int n,p;
int add(int x,int y) { x=(x+y)%p; return x<0?x+p:x; }
int mul(int x,int y) { return 1ll*x*y%p; }
int sub(int x,int y) { x=(x-y)%p; return x<0?x+p:x; }
struct mat{
int o[4][4];
}A,ans,KO;
mat operator*(mat aa,mat bb) {
static mat tmp;
for(int i=1;i<=3;i++) {
for(int j=1;j<=3;j++) {
int tp = 0;
for(int k=1;k<=3;k++) {
tp = add(tp,mul(aa.o[i][k],bb.o[k][j]));
}
tmp.o[i][j] = tp;
}
}
return tmp;
}
void _______() {
long long i, a, b, c, d;
a = 1;
b = 0;
c = 0;
// scanf("%lld %lld", &n, &p);
i = 1;
while (i <= n) {
i = i + 1;
b = a + b;
a = 2 * b - a + c;
c = 2 * b - a + c;
while (a >= p) {
a -= p;
}
while (a < 0) {
a += p;
}
while (b >= p) {
b -= p;
}
while (b < 0) {
b += p;
}
while (c >= p) {
c -= p;
}
while (c < 0) {
c += p;
}
}
d = a - 2 * b + c;
while (d >= p) {
d -= p;
}
while (d < 0) {
d += p;
}
cerr<<d<<endl;
}
void KSM(int b) {
for(;b;b>>=1,A=A*A)
if(b&1) ans = ans*A;
}
void solve() {
scanf("%lld%lld",&n,&p);
ans = A = KO;
A.o[1][1] = A.o[1][2] = A.o[1][3] = A.o[2][2] = A.o[3][1] = 1;
A.o[2][1] = 2; ans.o[1][1] = 1;
KSM(n);
int d = 0;
d = add(sub(ans.o[1][1],mul(2,ans.o[1][2])),ans.o[1][3]);
printf("%lld\n",d);
// _______();
}
main() {
freopen("program2.in","r",stdin);
freopen("./OUT/2.out","w",stdout);
int T = 10;
while(T--) solve();
}
t3
自然数幂和,求0次幂,1次幂,2次幂,3次幂,4次幂. 强行背一波公式 $ S_{0}(n) = n+1 $ $ S_{1}(n) = \frac{n*(n+1)}{2} $ $ S_{2}{n} = \frac{n(n+1)(2*n-1)}{6} $ $ S_{3}{n} = S_{1}^2(n) $ $ S_{4}{n} = S_{2} * \frac{3 * n ^ {2}+ 3 * n + 1 } {5} $ $$#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define int unsigned long long
using namespace std;
//int n = 1000000000000000;
int n;
int s1,s0,s2,s3,s4;
void HS() {
int i = 0;
while (i <= n) {
s0 = s0 + 1;
s1 = s1 + i;
s2 = s2 + i * i;
s3 = s3 + i * i * i;
s4 = s4 + i * i * i * i;
i = i + 1;
}
printf("%llu\n", s0);
printf("%llu\n", s0);
printf("%llu\n", s1);
printf("%llu\n", s1);
printf("%llu\n", s2);
printf("%llu\n", s2);
printf("%llu\n", s3);
printf("%llu\n", s3);
printf("%llu\n", s4);
printf("%llu\n", s4);
}
main() {
cin>>n;
// HS();
s0 = n+1;
s1 = (n/2)*(n+1);
s2 = (n/2)*((2*n+1)/3)*(n+1);
s3 = s1*s1;
s4 = (n/10)*((2*n+1)/3)*(n+1)*(3*n*n+3*n-1);
cout<<s0<<endl;
cout<<s0<<endl;
cout<<s1<<endl;
cout<<s1<<endl;
cout<<s2<<endl;
cout<<s2<<endl;
cout<<s3<<endl;
cout<<s3<<endl;
cout<<s4<<endl;
cout<<s4<<endl;
}
T5
问一个矩阵内多少个全1矩阵. 类同很多题目(如luogu仓鼠窝),裸上一个单调栈就好#include <iostream>
#include<cstdio>
#define pr std::pair<int,int>
const int N = 5011;
int n, m;
bool data[N][N];
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;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
data[i][j] = bool((next_rand() % 8) > 0);
}
pr sta[N];int top;
int hi[N];
long long count3(){
long long ans = 0;
for(int i=1;i<=n;i++) {
top = 0; int adc = 0;
for(int j=1;j<=m;j++) {
if(data[i][j]==0) {
hi[j] = 0; adc = 0; top = 0;
continue;
}
pr now = pr(++hi[j],1);
while(top&&now.first<=sta[top].first) {
adc -= sta[top].first*sta[top].second;
now.second += sta[top].second;
top--;
}
sta[++top] = now;
adc += now.first * now.second;
ans += adc;
}
}
for(int i=1;i<=m;i++) hi[i] = 0;
return ans;
}
int main(){
freopen("program5.in","r",stdin);
freopen("./OUT/5.out","w",stdout);
std::cin >> seed;
for(int i = 0; i < 10; i++){
generate_input();
std::cout << count3() << std::endl;
}
return 0;
}
T6
给你一个函数 $ F(X) = A*X^2 + B $,X初始值为0,T(狼狼范围)次自调用 $(X=F(X)) $之后X的值. 看上去很像Pollard-rho里的那个神奇随机函数? 利用判环算法找出循环节,就可以在跑5min之后找出答案啦#include <stdio.h>
#include<iostream>
unsigned long long a, b, c, t, k, n,tt;
void rd(unsigned long long &t) {
t = (t * t * a + b) % c;
}
int main() {
freopen("program6.in","r",stdin);
freopen("./OUT/6.out","w",stdout);
int i;
for (i = 0; i <= 9; i++) {
scanf("%llu %llu %llu %llu", &n, &a, &b, &c);
t = 0; tt = 0;
unsigned long long CIR = 1;
for(;;CIR++) {
rd(t);
rd(tt); rd(tt);
if(tt==t) break;
}
n-=CIR;
n%=CIR;
for(unsigned long long i=1;i<=n;i++) rd(t);
printf("%llu\n", t);
}
}
T7
16进制度(用字母代替)的数独.(也就是16宫格啦!) 直接爆搜,发现正着搜要挂,倒着爆搜枚举就可以了.#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
char s[20][20];
int er[21];
int h[22],l[22],o[22];
int ho(int x,int y) {
return (x/4)*4+y/4;
}
bool flag;
void dfs(int x,int y) {
if(x==-1) { flag = 1; return; }
if(y==-1) {
dfs(x-1,15); return;
}
if(s[x][y]!='?') {
dfs(x,y-1); return;
}
for(int i=0;i<=15;i++) {
if( ((h[x]&er[i])==0) && (0==(l[y]&er[i]) ) && (0==(o[ho(x,y)]&er[i]) ) ) {
h[x] ^= er[i];
l[y] ^= er[i];
o[ho(x,y)] ^= er[i];
s[x][y] = 'A' + i;
dfs(x,y-1);
if(flag) return;
s[x][y] = '?';
h[x] ^= er[i];
l[y] ^= er[i];
o[ho(x,y)] ^= er[i];
}
}
}
void solve(int points) {
for (int i = 0; i <= 15; i++) {
scanf("%s", s[i]);
h[i] = l[i] = o[i] = 0;
}
for(int i=0;i<=15;i++) {
for(int j=0;j<=15;j++) {
if(s[i][j]!='?') {
h[i]^=er[s[i][j]-'A'];
l[j]^=er[s[i][j]-'A'];
o[ho(i,j)]^=er[s[i][j]-'A'];
}
}
}
flag = 0;
dfs(15,15);
if (flag) {
for (int k = 0; k <= points - 1; k++) {
for (int i = 0; i <= 15; i++) {
printf("%s", s[i]);
}
printf("\n");
}
}
else{
for(int k=0;k<=points-1;k++)
printf("NO SOLUTION.\n");
}
}
int main() {
freopen("program7.in","r",stdin);
freopen("./OUT/7.out","w",stdout);
er[0] = 1;
for(int i=1;i<=20;i++) er[i] = er[i-1]*2;
solve(1);
solve(2);
solve(3);
solve(4);
return 0;
}
T8
给你一个八层循环的毒瘤代码.我们发现第一个答案显然是C(n,7),然后这是一个关于n的7次多项式.别的都和第一个的形式很像.大胆猜测这是一个关于n的7次多项式,发现模数是个质数,直接拉格朗日插值.#include <stdio.h>
#include<iostream>
unsigned long long a, b, c, d, e, f, g, q, r, s, t, u, v, w, x, y, z;
unsigned long long p = 1234567891;
void HANSHU(unsigned long long n) {
a = 0;
q = 0;
r = 0;
s = 0;
t = 0;
u = 0;
v = 0;
w = 0;
x = 0;
y = 0;
z = 0;
a = 0;
while (a < n) {
a = a + 1;
b = 0;
while (b < n) {
b = b + 1;
c = 0;
while (c < n) {
c = c + 1;
d = 0;
while (d < n) {
d = d + 1;
e = 0;
while (e < n) {
e = e + 1;
f = 0;
while (f < n) {
f = f + 1;
g = 0;
while (g < n) {
g = g + 1;
if (a < b && b < c && c < d && d < e && e < f && f < g) {
q = q + 1;
q = q % p;
}
if (a < b && c < g && c < d && e < f && a < d) {
r = r + 1;
r = r % p;
}
if (a < d && d < f && c < f && c < e && b < d) {
s = s + 1;
s = s % p;
}
if (d < e && b < d && a < f && d < e && b < g) {
t = t + 1;
t = t % p;
}
if (c < f && b < f && b < c && f < g && b < f) {
u = u + 1;
u = u % p;
}
if (b < d && b < c && d < f && c < e && b < e) {
v = v + 1;
v = v % p;
}
if (a < c && a < b && c < e && b < f && e < g) {
w = w + 1;
w = w % p;
}
if (b < d && b < f && a < g && c < g && a < e) {
x = x + 1;
x = x % p;
}
if (b < f && a < c && c < d && a < c && b < e) {
y = y + 1;
y = y % p;
}
if (d < e && e < f && a < d && c < g && b < d) {
z = z + 1;
z = z % p;
}
}
}
}
}
}
}
}
}
unsigned long long ksm(unsigned long long a,unsigned long long b) {
unsigned long long ans = 1;
for(;b;b>>=1,a=a*a%p)
if(b&1) ans = ans*a%p;
return ans;
}
unsigned long long Q[11],R[11],S[11],T[11],U[11],V[11],W[11],X[11],Y[11],Z[11];
unsigned long long laglang(unsigned long long *A,unsigned long long x) {
x%=p;
unsigned long long sm = 0;
for(unsigned long long i=1;i<=9;i++) {
unsigned long long s1 = 1; unsigned long long s2 = 1;
for(unsigned long long j=1;j<=9;j++) {
if(i==j) continue;
s1 = s1*((x-j+p)%p)%p;
s2 = s2*((i-j+p)%p)%p;
}
sm = (sm + A[i]*s1%p*ksm(s2,p-2)%p )%p;
}
return sm;
}
int main() {
for(unsigned long long i=1;i<=9;i++) {
HANSHU(i);
Q[i] = q; R[i] = r; S[i] = s; T[i] = t; U[i] = u; V[i] = v; W[i] = w;
X[i] = x; Y[i] = y; Z[i] = z;
}
unsigned long long N;
std::cin>>N;
printf("%llu\n",laglang(Q,N));
printf("%llu\n",laglang(R,N));
printf("%llu\n",laglang(S,N));
printf("%llu\n",laglang(T,N));
printf("%llu\n",laglang(U,N));
printf("%llu\n",laglang(V,N));
printf("%llu\n",laglang(W,N));
printf("%llu\n",laglang(X,N));
printf("%llu\n",laglang(Y,N));
printf("%llu\n",laglang(Z,N));
return 0;
}
T9
这是一个毒瘤,给你MD5的转换代码,输入给了你md5码叫你转换成原码,T10
题意自己看。 发现这道题开头有一个关于字母的循环调用,观察到规律,把开头那段关于字母的代码跑出以下代码之后替换掉就可以了。#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
ull o[30];
int main() {
ull sm = 0; o[0] = 1;
for(int i=1;i<=26;i++) {
sm += o[i-1];
o[i] = o[i-1]*(26-i)+sm;
printf("void %c(){__=__+___*%lluull;}\n",(char)(i+'A'-1),o[i]);
}
}
最后输出
void _(){__=__+___*1ull;}
void A(){__=__+___*26ull;}
void B(){__=__+___*651ull;}
void C(){__=__+___*15651ull;}
void D(){__=__+___*360651ull;}
void E(){__=__+___*7950651ull;}
void F(){__=__+___*167340651ull;}
void G(){__=__+___*3355140651ull;}
void H(){__=__+___*63923340651ull;}
void I(){__=__+___*1154150940651ull;}
void J(){__=__+___*19688020140651ull;}
void K(){__=__+___*316229927340651ull;}
void L(){__=__+___*4764358535340651ull;}
void M(){__=__+___*67038159047340651ull;}
void N(){__=__+___*876597565703340651ull;}
void O(){__=__+___*10591310445575340651ull;}
void P(){__=__+___*6772687681910030955ull;}
void Q(){__=__+___*5479948192676037227ull;}
void R(){__=__+___*12292036863279645291ull;}
void S(){__=__+___*11448514006979854955ull;}
void T(){__=__+___*5543854012881322603ull;}
void U(){__=__+___*7009382195709231723ull;}
void V(){__=__+___*14337023109848777323ull;}
void W(){__=__+___*6754098618987856491ull;}
void X(){__=__+___*2452069220114645611ull;}
void Y(){__=__+___*12294754496077775467ull;}
void Z(){__=__+___*3690695698331353707ull;}
小结:感觉今天花在这道毒瘤题上花费了太多时间了,考试遇到这种题还是要谨慎,不要一下子就沉迷进去那种,嘿嘿嘿,写完又得到十分的快感之中,很亏的,虽然时间越多分数,但却不是正比形式。以及遇到及时应变,总之实力如果有的话,除了像9问那种嘿嘿嘿题应该还是可以做的,还是要加强实力。