描述
17级学姐中有个学姐,人称撞杆子的CC,因为CC学姐走路的时候总是在低头玩手机,所以经常撞杆子,在一次把鼻子撞破后,CC学姐在想自己出一次门究竟要撞多少个杆子。一天CC学姐打算去广场玩,已知CC学姐走完全程共撞n次杆子,CC学姐第一次撞杆子时是走了1米的时候,每次撞完杆子后潜意识都会改变自己的小心程度,即第i次撞杆子后经过2i % 107米后会撞下一个杆子,现在CC学姐想知道自己走了多远
格式
输入格式
输入一个n(1 <= n <= 10^5),CC学姐走完全程要撞的杆子数量
输出格式
输出一个s,CC学姐走完全程所走的距离
样例
样例输入 Copy
1
3
4
样例输出 Copy
1
7
15
提示
多组测试数据,请在输入时循环输入到文件尾,共700组数据,请控制程序运行时间
分析题意:
撞n次杆子
第1次撞,走1米;( 2^0 m )
第i次撞杆子后(i+1次撞)经过2^i % 107 m后会撞下一个杆子
经过n次撞击,CC学姐走完全程所走的距离为
2^0
+2^1
+2^2
+……+2^n-1
根据这个公式,写出如下代码:
#include<stdio.h>
long long int fun(long long int a,long long int n)
{
long long int ans=0,s=1;//ans 用来累计走完全程所走的距离
while(n--)
{
ans+=s;
s=s*2%107;
//s从1开始,后面为2%107,4%107,8%107,16%107
}
return ans;
}
main()
{
int n;
while(~scanf("%d",&n))//输入要撞的杆子数n (1 <= n <= 10^5)
printf("%lld\n",fun(2,n));
//fun(2,n)是求CC学姐撞n个杆子走完全程所走的距离
}
当然,对于求2^i%107,可以想到用快速幂写。
先考虑a^b,再用取模公式
如求 5^10
1.指数10转二进制为1010
1 0 1 0
8 4 2 1
5^8 5^4 5^2 5^1
5^10 = 5^2 *5^8
二进制位为1,累乘,为0,不累乘
2. 从右至左依次取出1010的每一位
如b=10
b&1,(b>>1)&1,(b>>2)&1,(b>>3)&1………
直到b右移后为0停止
3.取模运算公式:
(ab) mod c = ((a mod c)(b mod c)) mod c
a^b mod c =((a mod c)^b) mod c
定义一个函数mode(int a,int b, int c),其作用为求a^b%c
b从0到n-1,在main函数中用for循环实现,并用ans累加
代码如下:
#include<stdio.h>
long long int mode(int a,int b,int c)//该函数作用求a^b%c
{
long long int ans=1;//用于累乘
a=a%c;
while(b){
if(b&1)//等同b%2==1
ans=ans*a%c;
a=a*a%c;
b>>=1; //等同b/=2;
}
return ans;
}
main()
{
int n;
while(~scanf("%d",&n))
{
long long int ans=0;
for(int i=0;i <= n-1;i++){
ans+=mode(2,i,107);
}
printf("%lld\n",ans);
}
}