zoukankan      html  css  js  c++  java
  • poj 2065 SETI(gauss--->≡)

    题目链接
    翻译链接

    分析:
    体面看了好久
    简单来说,就是有若干个同余方程
    a0*k^0+a1*k^1+a2^k^2+…=x1
    1<=k<=n,x1已知
    求解ai

    tip

    再用高斯消元同余方程的时候
    注意需要使用abs
    有一句话的作用我搞不大懂

    if (a[i][j]*a[j][i]<0) t=-t;

    看来只能记住了

    回带求值的过程在高斯消元解异或方程时是没有的

    //回带求值
    for (int i=n;i>=1;i--)
    {
        //解的情况的判断 
        if (a[i][i]==0&&a[i][n+1]%p!=0) return 0;   //无解
        else if (a[i][i]==0&&a[i][n+1]%p==0) continue;   //自由元
    
        //答案的处理
        ans[i]=((a[i][n+1]*KSM(a[i][i],p-2))%p+p)%p;
    
        //用第i个元素的答案,回带求解1~i-1
        for (int j=i-1;j>=1;j--)
            if (a[j][i])
                a[j][n+1]-=a[j][i]*ans[i],
                ((a[j][n+1]%=p)+=p)%=p;
    } 

    同余方程有一点好处,就是不用double,没有精度问题
    但是还是需要注意随时%,因为有减操作,所以随时+p%p

    //这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    
    using namespace std;
    
    const int N=100;
    int p,a[N][N],n,ans[N];
    
    int KSM(int a,int b)
    {
        a%=p;
        int t=1;
        while (b)
        {
            if (b&1)
                t=(t%p*a%p)%p;
            b>>=1;
            a=(a%p*a%p)%p;
        }
        return t%p;
    }
    
    int gauss()
    {
        for (int i=1;i<=n;i++)
        {
            int num=i;
            for (int j=i+1;j<=n;j++)
                if (abs(a[j][i])>abs(a[num][i])) num=j;
            //找到一行当前列的系数不为0     
            if (!a[num][i])
                continue;
    
            if (num!=i)
                for (int j=1;j<=n+1;j++)
                    swap(a[i][j],a[num][j]);
    
            for (int j=i+1;j<=n;j++)
                if (j!=i&&a[j][i])
                {
                    int t=((abs(a[j][i])%p*KSM(abs(a[i][i]),p-2)%p)%p+p)%p;
                    //系数化为一,除法变成乘法逆元 
    
                    if (a[i][j]*a[j][i]<0) t=-t;
    
                    for (int k=1;k<=n+1;k++)
                        a[j][k]-=t*a[i][k],
                        ((a[j][k]%=p)+=p)%=p;
                }
        }
    
        //回带求值
        for (int i=n;i>=1;i--)
        {
            //解的情况的判断 
            if (a[i][i]==0&&a[i][n+1]%p!=0) return 0;
            else if (a[i][i]==0&&a[i][n+1]%p==0) continue;
    
            //答案的处理
            ans[i]=((a[i][n+1]*KSM(a[i][i],p-2))%p+p)%p;
    
            //用第i个元素的答案,回带求解1~i-1
            for (int j=i-1;j>=1;j--)
                if (a[j][i])
                    a[j][n+1]-=a[j][i]*ans[i],
                    ((a[j][n+1]%=p)+=p)%=p;
        } 
        return 1;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while (T--)
        {
            char s[N];
            memset(a,0,sizeof(a));
            scanf("%d",&p);
            scanf("%s",&s);
            n=strlen(s);
            for (int i=0;i<strlen(s);i++)
                if (s[i]=='*') a[i+1][n+1]=0;
                else a[i+1][n+1]=s[i]-'a'+1;
            for (int i=1;i<=n;i++)
                for (int j=1;j<=n;j++)
                {
                    if (j==1)
                    {
                        a[i][1]=1;
                        continue;
                    }
                    a[i][j]=(a[i][j-1]*i)%p;
                }
            gauss();
            for (int i=1;i<n;i++) printf("%d ",ans[i]);
            printf("%d
    ",ans[n]);
        }
        return 0;
    }
  • 相关阅读:
    Android Static分析
    hdoj 1285 确定比赛名次 【拓扑排序】
    Sqoop2安装记录
    Activiti源代码分析
    SpringBoard 无法启动应用程序(错误:-3)
    关于public、private、protected、internal
    Java基础——Statement与PrepareStatement
    无password身份验证:安全、简单且部署高速
    说说Linux文件权限那些事儿
    Android中Service概述
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673068.html
Copyright © 2011-2022 走看看