[WC2015]未来程序(提交答案)

sub1:ans=a*b%c,龟速乘即可。

#include <stdio.h>
#include <stdlib.h>
unsigned long long a, b, c, d;
unsigned long long mul(unsigned long long a,unsigned long long b)
{
    unsigned long long x=0;
    while(b)
    {
        if(b&1)x=(x+a)%c;
        b>>=1,a=(a+a)%c;
    }
    return x;
}
void _() {
    scanf("%llu %llu %llu", &a, &b, &c);
    d = mul(a,b);
    printf("%llu\n", d);
}

int main() {
    freopen("program1.in","r",stdin);
    freopen("program1.out","w",stdout);
    _();
    _();
    _();
    _();
    _();
    
    _();
    _();
    _();
    _();
    _();
}
生成代码

sub2:发现是一个递推式,每次转移如下:a'=a+2b+c,b'=a+b,c'=a,直接构造3*3的矩阵,进行矩乘即可。

#include<cstdio>
#include<cstring>
using namespace std;
long long n,p;
struct mat{
    int a[3][3];
    mat(){memset(a,0,sizeof a);}
    void init(){memset(a,0,sizeof a);for(int i=0;i<3;i++)a[i][i]=1;}
    void prepare()
    {
        memset(a,0,sizeof a);
        a[0][0]=a[0][1]=a[0][2]=a[1][1]=a[2][0]=1,a[1][0]=2;
    }
};
mat operator*(mat a,mat b)
{
    mat c;
    for(int i=0;i<3;i++)
    for(int j=0;j<3;j++)
    for(int k=0;k<3;k++)
    c.a[i][j]=(c.a[i][j]+1ll*a.a[i][k]*b.a[k][j])%p;
    return c;
}
void _______() {
    scanf("%lld %lld", &n, &p);
    mat A,ret;
    A.prepare(),ret.init();
    while(n)
    {
        if(n&1)ret=ret*A;
        A=A*A,n>>=1;
    }
    long long a=ret.a[0][0],b=ret.a[0][1],c=ret.a[0][2],d=((a-2*b+c)%p+p)%p;
    printf("%lld\n", d);
}
int main() {
    freopen("program2.in","r",stdin);
    freopen("program2.out","w",stdout);
    _______();
    _______();
    _______();
    _______();
    _______();
    _______();
    _______();
    _______();
    _______();
    _______();
    return 0;
}
生成代码

sub3:求Σik,其中k∈[0,4],手算求答案即可,这个没写代码,计算器算算即可。

1000000000000001
1000000000000001
2538972135152631808
2538972135152631808
2806098670314569728
2806098670314569728
6570342264898322432
6570342264898322432
10067259324320137216
10067259324320137216
答案

sub4:随机生成n*n(n<=5000)的0/1矩阵,第一问求值为1的格子选2个进行排列的方案数,显然就是x*(x-1)(x为值为1的格子数);第二问是求对于每个值为1的格子,距离它最近的值为0的格子的距离,输出距离和,显然可以bfs多元最短路搜索,复杂度可以O(Tn2),大约5~10s能跑出答案

#include <iostream>
using namespace std;
const int N = 5000, inf = 0x3F3F3F3F;
int n, m, type,dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
bool mp[N + 11][N + 11],vis[N+11][N+11];
int qx[N*N+11],qy[N*N+11],d[N+11][N+11];
long long ans;
int seed;
int next_rand(){
    static const int P = 1000000007, Q = 83978833, R = 8523467;
    return seed = ((long long)Q * seed % P * seed + R) % P;
}
long long count1()
{
    ans = 0LL;
    for(int i = 0; i < n; i++)
    for(int j = 0; j < m; j++)
    if(mp[i][j])ans++;
    return ans*(ans-1);
}
long long count2()
{
    ans = 0LL;
    int qs=0,qe=0;
    for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    if(mp[i][j])vis[i][j]=0;
    else vis[i][j]=1,d[i][j]=0,qx[qe]=i,qy[qe++]=j;
    while(qs<qe)
    {
        int x=qx[qs],y=qy[qs++];
        for(int i=0;i<4;i++)
        {
            int u=x+dx[i],v=y+dy[i];
            if(u<0||u>=n||v<0||v>=m||vis[u][v])continue;
            vis[u][v]=1,d[u][v]=d[x][y]+1,qx[qe]=u,qy[qe++]=v;
            ans+=d[u][v];
        }
    }
    return ans;
}
int main(){
    freopen("program4.in","r",stdin);
    freopen("program4.out","w",stdout);
    cin >> seed;
    for(int i = 0; i < 10; i++){
        cin >> n >> m >> type;
        for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
        mp[i][j] = bool((next_rand() % 8) > 0);
        cout << (type == 1 ? count2() : count1()) <<endl;
    }
    return 0;
}
生成代码

sub5:随机生成n*n(n<=5000)的0/1矩阵,求全1矩阵个数。这题的简化版:https://www.cnblogs.com/hfctf0210/p/10852851.html

#include <iostream>

const int N = 5011;
int n, m,c[N][N],st[N];
bool data[N][N];
long long sum[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);
}
long long count3(){
    long long ret=0;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    c[i][j]=data[i][j]?c[i-1][j]+1:0;
    int top;
    for(int i=1;i<=n;i++)
    {
        st[0]=top=0;
        for(int j=1;j<=n;j++)
        if(!c[i][j])st[0]=j,top=0;
        else{
            while(top&&c[i][j]<=c[i][st[top]])top--;
            st[++top]=j,sum[top]=sum[top-1]+1ll*(j-st[top-1])*c[i][j];
            ret+=sum[top];
        }
    }
    return ret;
}

int main(){
    freopen("program5.in","r",stdin);
    freopen("program5.out","w",stdout);
    std::cin >> seed;
    for(int i = 0; i < 10; i++){
        generate_input();
        std::cout << count3() << std::endl;
    }

    return 0;
}
生成代码

sub6:发现式子还有自然溢出,快速幂/矩阵类显然不行,想到floyd套圈,学习笔记链接:https://www.cnblogs.com/hfctf0210/p/10725670.html,不过要跑300~400s

#include<iostream>
using namespace std;
typedef unsigned long long ull;
ull T,n,a,b,c;
ull s,t,tim,tn,tm;
int main()
{
    freopen("program6.in","r",stdin);
    freopen("program6.out","w",stdout);
    int T=10;
    while(T--)
    {
        cin>>n>>a>>b>>c;
        s=t=tn=0,tm=2;
        while(1)
        {
            t=(a*t*t+b)%c;
            tn++;
            if(s==t)break;
            if(tn==tm)tn=0,tm<<=1,s=t;
        }
        s=t=tim=0;
        while(tim<tn)t=(a*t*t+b)%c,tim++;
        tim=1;
        while(s!=t)s=(a*s*s+b)%c,t=(a*t*t+b)%c,tim++;
        tm=(n-tim)%tn+1;
        tim=1;
        while(tim<=tm)s=(a*s*s+b)%c,tim++;
        cout<<s<<endl;
    }
}
生成代码

sub8:把a~g当成7个点,化成图形,发现10张图需要枚举的变量均不超过2个,由于n%mod很小(大约1e6级别),对于需要枚举不超过1个的8张图,直接枚举即可,剩下2张图直接手推/枚举打表即可。

1018333390
993704934
1053807588
1144151985
712062141
530076748
520686243
337499021
820275783
80253986
答案

sub7/9/10:咕了,太菜了不会

猜你喜欢

转载自www.cnblogs.com/hfctf0210/p/10907965.html
wc