爆零赛(12.24)

71 篇文章 0 订阅
61 篇文章 0 订阅

平安夜的hu测
mdzz最近就是有点颓,明知道这次成绩要上报,还是妥妥的爆了零。。。
这份题的暴力打满了就是170。。。

T1

这里写图片描述
这里写图片描述

分析:

%60

做这道题之前,要了解一些复数运算
手玩了r的1~8次方之后,发现i前面一定会有一个sqrt(7),而常数项中一定没有sqrt(7)
实际上这就是复数的计算法则:
这里写图片描述

而我们需要求的答案也是符合这个形式的(只有i前面有sqrt(7))
那我们就可以把i前面的sqrt(7)抹掉
(但是如果遇到sqrt(7)i*sqrt(7)i,我们需要替换成-7

预处理r^23所有的a+bi中的a和b值

之后暴力搜索

这里有一个小细节:

因为状态只有01,为了降低常数,我们可以直接用二进制枚举

这是一种很重要的思想

#include<cstdio>
#include<cstring>
#include<iostream>
#define ll long long

using namespace std;

double x,y;
double a[30],b[30];
int num[30];
bool ff=0;

void cal(int i,int j,int k)
{
    a[k]=a[i]*a[j]-7*b[i]*b[j];    //b中都有一个sqrt(7),所以要替换成-7 
    b[k]=b[i]*a[j]+a[i]*b[j];
}

int pd(int num)
{
    double xx=0,yy=0;
    for (int i=0;i<24;i++)
        if (num&(1<<i)) xx+=a[i],yy+=b[i];
    return xx==x&&yy==y;
}

int main()
{
    freopen("verlauf.in","r",stdin);  
    freopen("verlauf.out","w",stdout);
    scanf("%lf%lf",&x,&y);
    a[0]=1.0; b[0]=0.0;
    a[1]=-0.5; b[1]=0.5;
    for (int i=2;i<30;i++)
    {
        if (i&1) cal(i-1,1,i);
        else cal(i/2,i/2,i);
    }

    for (int i=0;i<(1<<24);i++)    //8388608
        if (pd(i))
        {
            for (int j=0;j<24;j++)
                if (i&(1<<j)) printf("%d ",j);
            break;
        } 
    return 0;
}

T2

T3

这里写图片描述

分析:

40%

实际上这道题的部分分比较好想
什么都别多想,直接O(nk^2)

设计状态f[i][j],表示第i位上的数字是j的方案数

枚举每一位上的数字,判断相邻两数之间的gcd
直接计数即可

#include<cstdio>
#include<cstring>
#include<iostream>
#define ll long long

using namespace std;

const ll p=1000000007;
const int N=1000010;
int a[N],n,K;
int gcd[1002][1002];
ll ans=0,f[1002][1002];

int GCD(int a,int b)
{
    int r=a%b;
    while (r)
    {
        a=b;b=r;
        r=a%b;
    }
    return b;
}

int main()
{
    freopen("geburtstag.in","r",stdin);  
    freopen("geburtstag.out","w",stdout);
    for (int i=1;i<=1000;i++)
        for (int j=1;j<=i;j++)
            gcd[i][j]=gcd[j][i]=GCD(i,j);

    scanf("%d%d",&n,&K);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);

    for (int i=1;i<=a[1];i++) f[1][i]=1;
    for (int i=2;i<=n;i++)
        for (int j=1;j<=a[i-1];j++)
            for (int k=1;k<=a[i];k++)
                if (gcd[j][k]<=K)
                    f[i][k]=(f[i][k]%p+f[i-1][j]%p)%p;
    for (int i=1;i<=a[n];i++) ans=(ans+f[n][i]%p)%p;
    printf("%lld",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值