M斐波那契数列F[n]是一种整数数列,它的定义如下:
F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )
现在给出a, b, n,你能求出F[n]的值吗?
第一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )
输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可。
6 10 2
60
枚举几项:
N | 表达式 |
---|---|
0 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
… | … |
所以就会发现,a,b的指数是呈斐波那契数列的关系
这样问题就简单了,由于n会很大,所以可以用矩阵乘法加速递推,a%p的运算用费马小定理。
Code:
#include <stdio.h>
#include <string.h>
#define MOD 1000000007
typedef long long ll;
struct matrix
{
ll a[3][3];
}v,ans;
ll a,b,n;
ll quick_pow(ll x,ll y)
{
ll ans=1;
x=x%MOD;
while(y)
{
if(y%2==1)
{
ans=(ans*x)%MOD;
}
y/=2;
x=(x*x)%MOD;
}
return ans;
}
void init()
{
memset(ans.a,0,sizeof(ans.a));
ans.a[0][0]=ans.a[1][1]=ans.a[2][2]=1;
v.a[0][0]=v.a[0][1]=v.a[1][0]=1,v.a[1][1]=0;
}
matrix mul(matrix x,matrix y)
{
matrix tmp;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
tmp.a[i][j]=0;
for(int k=0;k<3;k++)
{
tmp.a[i][j]+=(x.a[i][k]*y.a[k][j]);
tmp.a[i][j]%=(MOD-1); //给幂取模要取(MOD-1)
}
}
}
return tmp;
}
void cal(ll n)
{
while(n)
{
if(n&1)
{
ans=mul(ans,v);
}
n>>=1;
v=mul(v,v);
}
}
int main()
{
init();
scanf("%lld%lld%lld",&a,&b,&n);
init();
if(a==0||b==0)
{
puts("0");
return 0;
}
cal(n-1);
ll p=quick_pow(a,ans.a[0][1]);
ll q=quick_pow(b,ans.a[0][0]);
printf("%lld\n",((p%MOD)*(q%MOD))%MOD);
return 0;
}
因为题中要求的约数包括1和该数本身,所以对于一个数的约数倒数和通分之后的分母就是这个数本身(也就是题中的A),而分子是约数和。
所以可以得到下面的式子:
所以只需要判断
Code:
#include <stdio.h>
#include <string.h>
typedef long long ll;
ll a,b1,b2,n;
ll count(ll num)
{
ll cnt=0;
for(ll i=1;i<=num;i++)
{
if(num%i==0)
{
cnt+=i;
}
}
return cnt;
}
int main()
{
freopen("genius.in","r",stdin);
freopen("genius.out","w",stdout);
while(~scanf("%lld%lld%lld",&a,&b1,&b2)&&a&&b1&&b2)
{
if((a*b2)%b1!=0)
{
puts("0");
continue;
}
n=(a*b2)/b1;
if(count(n)==a)
{
printf("1 %lld\n",n);
}
else printf("0\n");
}
return 0;
}
Time Limit: 3 Seconds Memory Limit: 65536 KB
You are given four positive integers m,n,p,q(p < m and q < n). There are four points A(0,0),B(p,0),C(m,q),D(m,n). Consider the path f from A to D and path g from B to C. f and g are always towards and parallel to the positive direction of one axis, and they can only change their direction on integer points(whose coordinates are both integers).
You are asked to count the number(mod 100000007) of pair (f,g) that f and g have no intersection.
There are multiple cases(less than 100). Each case is a line containing four integers m,n,p,q(m ≤ 100000 and n ≤ 100000).
For each case, output a single line containing the right answer.
2 2 1 1
3 2 1 1
3
6
4个点A(0,0),B(p,0),C(m,q),D(m,n),保证m>p,n>q,求从A走到D和从B走到C两条路径不相交的走法的种数,只能up和right。
补集转化的思想,不相交的走法相当于所有的走法减去相交的走法。
而我们又知道从A到C和从B到D路径必相交,所以就可以用C(n+m,n) * C(m-p+q,q) - C(m+q,q) * C(m+n-p,n)来求得答案。
而对于组合数取模已经都很熟悉了。
Code:
#include <stdio.h>
#define mod 100000007
typedef long long ll;
ll n,m,p,q;
ll x=1,y=0;
ll ret;
ll suma,sumb;
ll ans_a,ans_b,ans_c,ans_d;
void Exgcd(ll a,ll b)
{
if(b==0)
{
x=1;
y=0;
}
else
{
Exgcd(b,a%b);
ll t=x;
x=y;
y=t-a/b*x;
}
}
void mulipy(ll n,ll m)
{
for(ll i=m+1;i<=n;i++)
{
suma*=i;
suma=suma%mod;
sumb*=i-m;
sumb=sumb%mod;
}
}
ll get(ll n,ll m)
{
suma=sumb=1;
mulipy(n,m);
Exgcd(sumb,mod);
x=(x%mod+mod)%mod;
long long ans=(x*suma)%mod;
return ans;
}
void f(ll num)
{
num%=mod;
}
int main()
{
while(scanf("%lld%lld%lld%lld",&m,&n,&p,&q)!=EOF)
{
ans_a=get(n+m,n); f(ans_a);
ans_b=get(m-p+q,q); f(ans_b);
ans_c=get(m+q,q); f(ans_c);
ans_d=get(m+n-p,n); f(ans_d);
printf("%lld\n",((ans_a*ans_b)%mod-(ans_c*ans_d)%mod+mod)%mod);
}
return 0;
}
POJ1365传送门
题意就是给你一个数分解质因数的形式之后,求出这个数减一的分解质因数的形式。
除了读入麻烦外剩下就是裸题。
Code:
#include <stdio.h>
#include <string.h>
#define MAXN 100000
int ans,k;
int cnt[MAXN];
int prime[MAXN];
char s[MAXN];
int quick_pow(int x,int y)
{
int ans=1;
while(y)
{
if(y%2==1)
{
ans=(ans*x);
}
y/=2;
x=(x*x);
}
return ans;
}
void div(int n)
{
memset(prime,0,sizeof(prime));
memset(cnt,0,sizeof(cnt));
k=1;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
prime[k]=i;
while(n%i==0)
{
cnt[k]++;
n/=i;
}
k++;
}
}
if(n!=1)
{
prime[k]=n;
cnt[k++]=1;
}
}
int main()
{
while(1)
{
ans=1;
gets(s);
if(s[0]==‘0‘)
{
break;
}
int len=strlen(s),tmp=0,t=0,x,y;
for(int i=0;i<=len;i++)
{
if(s[i]==‘ ‘||s[i]==‘\0‘)
{
t++;
if(t%2==1) x=tmp;
else
{
y=tmp;
ans=ans*quick_pow(x,y);
}
tmp=0;
continue;
}
tmp=tmp*10+(s[i]-‘0‘);
}
ans--;
div(ans);
for(int i=k-1;i>=1;i--)
{
printf("%d %d ",prime[i],cnt[i]);
}
printf("\n");
}
return 0;
}
Given a,b,c,d, find a fraction p/q with minimum q, and satisfied a/b < p/q < c/d .
For each test case, one line contains four integers a,b,c,d .
For each test case, print the fraction(see the sample for details).If multiple solution exists, output the one with minimum p.
1 3 1 2
2 1 3 1
2 1 4 1
1000 1001 1001 1002
2/5
5/2
3/1
2001/2003
Dataset 1: a,b,c,d ( 1 <= a,b,c,d <= 1e9, and a/b < c/d )
Added by: Race with time
Date: 2009-02-19
Time limit: 3s
Source limit: 50000B
Memory limit: 1536MB
Cluster: Cube (Intel Pentium G860 3GHz)
Languages: All except: ERL JS NODEJS PERL 6 VB.net
Resource: Code Craft 09
神犇题解:Click Here!
连分数解法:
设[a/b]表示a/b向下取整
如果a/b >= 1,设k = [a/b],可以知道 ( a/b ) - k < ( p/q ) - k < ( c/d ) - k,即 (a-bk)/b < (p - qk)/q < ( c- dk) / d,设a’ = a - bk,p’ = p - qk,c’ = c - dk,则求出a’/b < p’/q < c’/d的解以后,p = p’ + qk,可以得到真实的p和q。
如果a/b<1
如果c/d>1,那么p = q = 1
如果c/d<=1,那么问题可以转化为d/c < q/p < b/a
Code:
#include <stdio.h>
#include <string.h>
typedef long long ll;
ll a,b,c,d;
ll find(ll a,ll b,ll c,ll d)
{
if(a<b)
{
if(c>d) return 1;
else return find(d,c,b,a)*d/c+1;
}
else
{
int k=a/b;
return find(a-k*b,b,c-k*d,d);
}
}
int main()
{
while(~scanf("%lld%lld%lld%lld",&a,&b,&c,&d))
{
ll q=find(a,b,c,d);
ll p=q*a/b+1;
printf("%lld/%lld\n",p,q);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/z_mendez/article/details/47404355