math_5

45 篇文章 0 订阅
7 篇文章 0 订阅

math_5


我的疯狂被屠


【问题描述】

我是一个傻×蒟蒻,总是被屠,最近连INDEX都开始屠我了,55555~
我研究了一下每天屠我的人的总数,发现这样一个规律。
首先,每个人都只会屠我一次,然后就不屑于屠我了。
第一天有 1 个人屠了我,第二天有 1 个人屠了我,但是从第三天开始,之前两天屠我的人会告诉他们的一个朋友(当然是没有屠过我的),让他们来屠我。
结果,从某时候起,居然连外星人都不远千里来到地球开始屠我了。
作为一个傻×蒟蒻真diaosi,我知道,如果一天被屠 X 次,则你的RP会上涨 X2 点。
到今天为止,我已经被屠了 N 天。
我想算一算这 N 天我获得了多少点RP,但是我还得去选取数字,就拜托你了。
勇敢的骚年啊快去创造奇迹!


【输入】

输入文件名为crazy.in。
输入一行一个正整数 N ,表示我已经被屠天数。


【输出】

输出文件名为crazy.out。
输出一行一个整数,代表我获得的RP量,因为数字过大,所以对 1000000007 取模。


【输入样例】

4


【输出样例】

15


【样例解释】

第一天被屠 1 次,第二天被屠 1 次,第三天被屠 2 次,第四天被屠 3 次。
总计Rp值为 1+1+4+9=15


【数据范围】

对于 20% 的数据,保证有 1n20
对于 50% 的数据,保证有 1n105
对于 100% 的数据,保证有 1n1015


Solution

打表发现

i=1nFib2(i)=Fib(n)Fib(n+1)

证明:

n=1 时:
上式显然成立。

n>1 时:
假设 n1 时成立,即

i=1n1Fib2(i)=Fib(n)Fib(n1)


i=1nFib2(i)=(i=1n1Fib2(i))+Fib2(n)=Fib(n)Fib(n1)+Fib(n)Fib(n)=Fib(n)Fib(n+1)

综上,上式对于一切正整数皆成立。
然后就只需要 O(logn) 求斐波那契数列即可。

我用了一种奇葩的非矩阵版的求法,读者有兴趣可以看一看代码,原理是

Fib(n)=Fib(m+1)Fib(nm)+Fib(m)Fib(nm1)


Code

#include <iostream>
#include <cstdio>

#define MOD 1000000007
#define LL long long

LL pre,post;
LL n;

void pyh(LL x){
    if(x==1){pre=1;post=0;return;}
    if(x==2){pre=post=1;return;}
    if(x&1){
        pyh(x-1);
        pre=(pre+post)%MOD;
        post=((pre-post)%MOD+MOD)%MOD;
        return;
    }
    pyh(x/2);
    LL fp=pre,fpo=post;
    pre=(fp*fp%MOD+2*fp%MOD*fpo%MOD)%MOD;
    post=(fp*fp%MOD+fpo*fpo%MOD)%MOD;
}

int main(){

    freopen("crazy.in","r",stdin);
    freopen("crazy.out","w",stdout);

    scanf("%lld",&n);
    pyh(n+1);
    printf("%lld\n",pre*post%MOD);

    return 0;
}

我的数字选取


【问题描述】

黑了很多人今天来黑下自己。
其实每个数字都是有灵魂的。
譬如说我,能被 2 整除的数字看起来都有点 2
能被 4 整除的数字不仅 2 还一脸死相。
能被 5 整除的数字看起来昨天才哭过。
能被 7 整除的数字,原来就是你把 5 弄哭的!
好吧,蛋疼到这里结束。
其实做数据是很累人的,不管你们信不信,反正我是信了。
每次其实我都想这么出数据。
首先决定我今天的幸运数字,然后再选定若干个悲剧数字,一个数字是幸运的定义为能够整除我今天的幸运数字而且不能够整除那若干个悲剧数字,最后选定一个区间 [L,R],将这个区间中所有的幸运的数字挑出来。
我想知道,我究竟能挑出多少个幸运的数字?
Note:幸运的数字和我今天的幸运数字不是同一个东西。


【输入】

输入文件名为Lucky.in。
第一行 4 个正整数 LN N L R ,分别表示我今天的幸运数字、悲剧数字的个数、区间的左界、区间的右界。
第二行包含 N 个正整数,表示若干个悲剧数字。


【输出】

输出文件名为Lucky.out。
输出仅一行,即我能挑出的幸运的数字的个数。


【输入样例】

2 1 3 4
7


【输出样例】

1


【数据范围】

对于 30% 的数据,保证有 0n2 1LR105
对于 100% 的数据,保证有 0n15 1LR1015 ,今天的幸运数字和悲剧数字均可用无符号32位整型变量存下。


Solution

容斥原理:
答案=能被今天的幸运数字整除的数的个数-能被今天的幸运数字和至少一个悲剧数字整除的数的个数+能被今天的幸运数字和至少两个悲剧数字整除的数的个数……
因为悲剧数字的个数不超过 15 ,所以可以搜索。


Code

#include <iostream>
#include <cstdio>

#define LL long long

using namespace std;

LL ln,n,l,r;
short mu[]={1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1};
LL chse[20],ans=0,num[20];

LL gcd(LL x,LL y){
    return y==0?x:gcd(y,x%y);
}

void kan(){
    LL tmp=ln;
    for(LL i=1;i<=chse[0];i++){
        tmp=tmp/gcd(tmp,chse[i])*chse[i];
        if(tmp>r||tmp<0)return;
    }
    ans+=mu[chse[0]]*(r/tmp-(l-1)/tmp);
}

void dfs(LL now){
    if(now==n+1){kan();return;}
    dfs(now+1);
    chse[++chse[0]]=num[now];
    dfs(now+1);
    chse[0]--;
}

int main(){

    freopen("lucky.in","r",stdin);
    freopen("lucky.out","w",stdout);

    scanf("%lld%lld%lld%lld",&ln,&n,&l,&r);
    for(LL i=1;i<=n;i++)scanf("%lld",&num[i]);

    dfs(1);

    printf("%lld\n",ans);

    return 0;
}

我的喂养计划


【问题描述】

众所周知,一中2011届信息组有许多胖子。
无奈他们体型过于巨大,于是,他们就请我来节制他们的饮食。
我决定,每天喂他们吃粥,这样既可以保证营养,又可以减肥。
但是,粥一旦多了,他们就觉得不爽,觉得自己长胖了,粥一旦少了,就不能让他们该题目和考试了。
经过长期观察研究,最适合的粥量为 N ,多一分不行,少一分不干。
悲剧的是,我只有两个勺子,而且它们的容量分别为 A B
当然,装粥的那口缸和盛着刚做好的粥的锅是非常大的,你可以将它们的容量视为无穷大。
每次,我只能使用一个勺子,用锅里的粥将这个勺子装满,然后倒入缸里面,或者用缸里面的粥将这个勺子倒满,然后放回锅里。
对了,每天锅里的粥可以视为无穷大。
我比较怕麻烦,希望知道一个最小的操作次数。
当然,他们要我节制他们若干天,所以每天的最适合粥量可能不同。
但是,勺子是不会换的(囧)。


【输入】

输入文件名为Feed.in。
输入第一行为两个正整数 A B ,分别表示两个勺子的容量。
接下来若干行,每行一个正整数,代表某一天的最适合粥量。


【输出】

输出文件名为Feed.out。
输出若干行,对应于输入中某一最适合粥量的最小操作次数。
如果不能刚好达到最适合粥量,那么输出”BeiJu!”,不含引号。


【输入样例】

2 4
3
2


【输出样例】

BeiJu!
1


【数据范围】

对于 50% 的数据,保证有 1A,B,N105 ,数据组数等于 1
对于 100% 的数据,保证有 1A,B,N109 ,数据组数不超过 1000


Solution

题目要求的即为满足 Ax+By=N 的使 |x|+|y| 最小的整数 x y

用扩展欧几里得求出一组特殊解 x0 y0 ,则通解为

x=x0+tBGcd(A,B),y=y0tAGcd(A,B)(tZ)

x0>0y0>0 ,且 BGcd(A,B)AGcd(A,B) ,则可以令 t 的系数小的那个变量变大,而另一个变小,则 |x|+|y| 会变小,直到变小的那个变量的绝对值小于 t 的系数为止。
BGcd(A,B)=AGcd(A,B),则执行上述操作不影响答案。

x0 y0 异号,则令大于 0 的变量变小,而小于 0 的变量变大,答案会变得更优,直到两个变量的绝对值有一个小于其 t 的系数为止。

x0<0y0<0,则同理 x0>0y0>0 的情况,也可以使得一个变量的绝对值小于 t 的系数为止。

综上所述,不管是哪种情况, x y 中必有一个的绝对值小于 t 的系数。
所以分四种情况讨论即可(讨论是 x 还是 y,讨论是正还是负)。


Code

#include <iostream>
#include <cstdio>

#define LL long long
#define Min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>0?(x):((-1)*(x)))

#define INF (9223372036854775807LL)

using namespace std;

LL a,b,ta,tb,x,y,G,n,ans;

LL ex_gcd(LL fa,LL fb,LL &fx,LL &fy){
    if(fb==0){fx=1;fy=0;return fa;}
    LL ffx,ffy;
    LL c=ex_gcd(fb,fa%fb,ffx,ffy);
    fx=ffy;
    fy=ffx-(fa/fb)*ffy;
    return c;
}

int main(){

    freopen("feed.in","r",stdin);
    freopen("feed.out","w",stdout);

    scanf("%lld%lld",&a,&b);
    G=ex_gcd(a,b,x,y);

    ta=a/G;tb=b/G;

    while(scanf("%lld",&n)!=EOF){
        if(n%G!=0){
            printf("BeiJu!\n");
            continue;
        }
        ans=INF;
        LL x0=x*(n/G),y0=y*(n/G),rx,ry;
//----------------------------------------------------------------------------
        rx=x0%tb;ry=y0+ta*(x0/tb);
        ans=Min(abs(rx)+abs(ry),ans);
//----------------------------------------------------------------------------
        rx-=tb;ry+=ta;
        ans=Min(abs(rx)+abs(ry),ans);
//----------------------------------------------------------------------------
        ry=y0%ta;rx=x0+tb*(y0/ta);
        ans=Min(abs(rx)+abs(ry),ans);
//----------------------------------------------------------------------------
        ry-=ta;rx+=tb;
        ans=Min(abs(rx)+abs(ry),ans);
//----------------------------------------------------------------------------
        printf("%lld\n",ans);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值