暴力求规律+高斯消元找系数+小数转分数+逆元 解决规律题

例题:2018icpc南京现场赛-G Pyramid

题目链接:http://codeforces.com/gym/101981/attachments

或者:https://nanti.jisuanke.com/t/A2144 

暴力找规律

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define pppp cout<<endl;
#define EPS 1e-6
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x3f3f3f3f      //1061109567
#define LL_INF 0x3f3f3f3f3f3f3f3f //4557430888798830399
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
vector<pair<double,double> >v;
struct point
{
    double x, y;
    point() {}
    point(double a, double b)
    {
        x = a;
        y = b;
    }
};
double h = 0.5 *sqrt(3);
double len(pair<double,double>a, pair<double,double>b)
{
    return (a.first-b.first)*(a.first-b.first)+(a.second-b.second)*(a.second-b.second);
}
bool eques(double a, double b)
{
    if(fabs(a-b)<EPS)
        return true;
    return false;
}
int main()
{
    v.push_back(make_pair(0,0));
    for(int i = 1; i <= 20; i++)
    {
        if(i&1)
        {
            for(int j = 0; j < i/2+1; j++)
            {
                v.push_back(make_pair(j*1.0+0.5,-i*h));
                v.push_back(make_pair(-j*1.0-0.5,-i*h));
            }
        }
        else
        {
            v.push_back(make_pair(0,-i*h));
            for(int j = 1; j <= i/2; j++)
            {
                v.push_back(make_pair(j*1.0,-i*h));
                v.push_back(make_pair(-j*1.0,-i*h));
            }
        }
        int cnt = 0;
        for(int j = 0; j < (int)v.size(); j++)
        {
            for(int k = j+1; k < (int)v.size(); k++)
            {
                for(int g = k+1; g < (int)v.size(); g++)
                {
                    if(eques(len(v[j],v[k]),len(v[k],v[g])) && eques(len(v[j],v[k]),len(v[j],v[g])))
                        cnt++;
                }
            }
        }
        printf("%d\n",cnt);
    }
    return 0;
}

打表找下规律,打表方法:把所有点扔坐标系里n^3爆搜即可

打出来为 1,5,15,35,70,126,210..

没感觉,作差 4, 10, 20, 35, 56, 84

还是没感觉,作差 6, 10, 15, 21, 28

发现此时的差递增1?也就是再作差4, 5, 6, 7是等差数列

也就是再作差1, 1, 1为常数

相当于函数AnAn求四次导为常数!(如果他是个连续函数的话)

于是我们设A_n=a*n^4+b*n^3+c*n^2+d*n+e(别忘记常数).

然后高斯消元求系数

高斯消元

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=105;
double a[maxn][maxn];
double b[maxn];
void GS(double a[][105], double b[], int n)
{
    //判断能否用高斯消元法,如果矩阵主对角线上有0元素存在是不能用的
    for(int i=0; i<n; i++)
        if (!a[i][i])
            return ;

    double c[n];    //存储初等行变换的系数,用于行的相减
    double x[n];    //解的存储数组

    //消元的整个过程如下,总共n-1次消元过程。
    for(int k=0; k<n-1; k++)
    {
        for(int i=k+1; i<n; i++)//求出第K次初等行变换的系数
            c[i]=a[i][k]/a[k][k];
        for(int i=k+1; i<n; i++)//第K次的消元计算
        {
            for(int j=0; j<n; j++)
                a[i][j]=a[i][j]-c[i]*a[k][j];
            b[i]=b[i]-c[i]*b[k];
        }
    }

    x[n-1] = b[n-1]/a[n-1][n-1];//先计算出最后一个未知数
    for (int i=n-2; i>=0; i--)//求出每个未知数的值
    {
        double sum=0;
        for (int j=i+1; j<n; j++)
            sum+= a[i][j]*x[j];
        x[i]=(b[i]-sum)/a[i][i];
    }
    for (int i=0; i<n; i++)
        printf("x%d = %0.10lf\n",i+1,x[i]);

}
int main()
{

    int n;//表示有几个未知数
    scanf("%d",&n);
    for(int i=0; i<n; ++i)
        for(int j=0;j<n;++j)
            scanf("%lf",&a[i][j]);
    for(int i=0; i<n; ++i)
        scanf("%lf",&b[i]);

    GS(a,b,n);

    return 0;
}

需要输入的数据,前五项
5
1 1 1 1 1
16 8 4 2 1
81 27 9 3 1
256 64 16 4 1
625 125 25 5 1
1 5 15 35 70

得到结果
x1 = 0.0416666667
x2 = 0.2500000000
x3 = 0.4583333333
x4 = 0.2500000000
x5 = -0.0000000000

纯小数(有限或者循环)转分数

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int Gcd_(int x,int y)           //  求最大公约数
{
    return y ? Gcd_(y, x%y) : x;
}

void Get_ans(char *s)
{
    int len=strlen(s);
    int a=0,b=0;
    int M1=0,M2=0;
    int flag=0;//判断是否为循环小数
    for(int i = 2; i < len; i++)
    {
        if(s[i] == '(')
            break;
        a=a*10+s[i]-'0';
        M1++;//分母中0的个数
    }
    for(int i = 2; i < len; i++)
    {
        if(s[i] == '(' || s[i] == ')')
        {
            flag = 1;
            continue;
        }
        b=b*10+s[i]-'0';
        M2++;
    }
    M2 -= M1;//分母中9的个数
    int Num = b - a;//分子
    int Den = 0;//分母
    if(!flag)
    {
        Num = b;
        Den = 1;
        M2 = 0;
    }
    for(int i = 0; i < M2; i++)
        Den = Den * 10 + 9;
    for(int i = 0; i < M1; i++)
        Den *= 10;
    int Gcd = Gcd_(Num, Den);
    Den /= Gcd;
    Num /= Gcd;
    printf("%d/%d\n", Num, Den);
    return;
}

int main()
{
    char s[20];
    scanf("%s", s);
    Get_ans(s);
    return 0;
}

需要输入格式为 浮点数不循环部分+(循环部分) 例如

x1 = 0.0416666667  输入 0.041(6)  得到1/24

x2 = 0.2500000000 输入 0.25 得到1/4

3 = 0.4583333333   输入0.458(3) 得到11/24

x4 = 0.2500000000  输入 0.25 得到1/4

化简得到公式

A_n=\frac{n^4+6*n^3+11*n^2+6*n}{24}\%1000000007

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define pppp cout<<endl;
#define EPS 1e-6
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x3f3f3f3f      //1061109567
#define LL_INF 0x3f3f3f3f3f3f3f3f //4557430888798830399
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
const LL mod=1e9+7;
LL Pow(LL x,LL n)
{
    LL ret=1;
    while(n)
    {
        if(n&1LL)
            ret=ret*x%mod;
        x=x*x%mod;
        n=n/2LL;
    }
    return ret;
}
int main()
{
    int T;
    scanf("%d",&T);
    LL inv=Pow(24LL,mod-2LL);//24关于1000000007的逆元41666667LL
    while(T--)
    {
        LL x;
        scanf("%lld",&x);
        LL sum = x*x%mod*x%mod*x%mod + x*x%mod*x%mod*6LL%mod + x*x%mod*11LL%mod + x*6LL%mod;
        sum = sum%mod*inv%mod;
        printf("%lld\n",sum);
    }
    return 0;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值