math_5
我的疯狂被屠
【问题描述】
我是一个傻×蒟蒻,总是被屠,最近连INDEX都开始屠我了,55555~
我研究了一下每天屠我的人的总数,发现这样一个规律。
首先,每个人都只会屠我一次,然后就不屑于屠我了。
第一天有
1
个人屠了我,第二天有
结果,从某时候起,居然连外星人都不远千里来到地球开始屠我了。
作为一个傻×蒟蒻真diaosi,我知道,如果一天被屠
X
次,则你的RP会上涨
到今天为止,我已经被屠了
N
天。
我想算一算这
勇敢的骚年啊快去创造奇迹!
【输入】
输入文件名为crazy.in。
输入一行一个正整数
N
,表示我已经被屠天数。
【输出】
输出文件名为crazy.out。
输出一行一个整数,代表我获得的RP量,因为数字过大,所以对
【输入样例】
4
【输出样例】
15
【样例解释】
第一天被屠
1
次,第二天被屠
总计Rp值为
1+1+4+9=15
【数据范围】
对于
20%
的数据,保证有
1≤n≤20
。
对于
50%
的数据,保证有
1≤n≤105
。
对于
100%
的数据,保证有
1≤n≤1015
。
Solution
打表发现
证明:
n=1
时:
上式显然成立。
n>1
时:
假设
n−1
时成立,即
则
综上,上式对于一切正整数皆成立。
然后就只需要
O(logn)
求斐波那契数列即可。
我用了一种奇葩的非矩阵版的求法,读者有兴趣可以看一看代码,原理是
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
整除的数字看起来都有点
能被
4
整除的数字不仅
能被
5
整除的数字看起来昨天才哭过。
能被
好吧,蛋疼到这里结束。
其实做数据是很累人的,不管你们信不信,反正我是信了。
每次其实我都想这么出数据。
首先决定我今天的幸运数字,然后再选定若干个悲剧数字,一个数字是幸运的定义为能够整除我今天的幸运数字而且不能够整除那若干个悲剧数字,最后选定一个区间
我想知道,我究竟能挑出多少个幸运的数字?
Note:幸运的数字和我今天的幸运数字不是同一个东西。
【输入】
输入文件名为Lucky.in。
第一行
4
个正整数
第二行包含
【输出】
输出文件名为Lucky.out。
输出仅一行,即我能挑出的幸运的数字的个数。
【输入样例】
2 1 3 4
7
【输出样例】
1
【数据范围】
对于
30%
的数据,保证有
0≤n≤2
,
1≤L≤R≤105
。
对于
100%
的数据,保证有
0≤n≤15
,
1≤L≤R≤1015
,今天的幸运数字和悲剧数字均可用无符号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
,多一分不行,少一分不干。
悲剧的是,我只有两个勺子,而且它们的容量分别为
当然,装粥的那口缸和盛着刚做好的粥的锅是非常大的,你可以将它们的容量视为无穷大。
每次,我只能使用一个勺子,用锅里的粥将这个勺子装满,然后倒入缸里面,或者用缸里面的粥将这个勺子倒满,然后放回锅里。
对了,每天锅里的粥可以视为无穷大。
我比较怕麻烦,希望知道一个最小的操作次数。
当然,他们要我节制他们若干天,所以每天的最适合粥量可能不同。
但是,勺子是不会换的(囧)。
【输入】
输入文件名为Feed.in。
输入第一行为两个正整数
接下来若干行,每行一个正整数,代表某一天的最适合粥量。
【输出】
输出文件名为Feed.out。
输出若干行,对应于输入中某一最适合粥量的最小操作次数。
如果不能刚好达到最适合粥量,那么输出”BeiJu!”,不含引号。
【输入样例】
2 4
3
2
【输出样例】
BeiJu!
1
【数据范围】
对于
对于
Solution
题目要求的即为满足
Ax+By=N
的使
|x|+|y|
最小的整数
x
、
用扩展欧几里得求出一组特殊解 x0 , y0 ,则通解为
若 x0>0,y0>0 ,且 BGcd(A,B)≠AGcd(A,B) ,则可以令 t 的系数小的那个变量变大,而另一个变小,则
若
若
x0
与
y0
异号,则令大于
0
的变量变小,而小于
若
综上所述,不管是哪种情况,
所以分四种情况讨论即可(讨论是
x
还是
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;
}