感觉今天好颓啊,我才把昨晚那五道题a了,(但我明明一直在学啊,为啥这么慢,难道是我太笨了?)
闲话少叙,先说做法
问题 A: C Looooops
题目描述
对于C的for(i=A ; i!=B ;i +=C)循环语句,给出A,B,C和k(k表示变量是在k进制下的无符号整数),判断循环次数,不能终止输出"FOREVER".
输入
多组数据,每组一行,A,B,C,k
程序以0 0 0 0结束
输出
一行一个整数,表示循环次数,或者"FOREVER"
样例输入
3 3 2 16 3 7 2 16 7 3 2 16 3 4 2 16 0 0 0 0
样例输出
0 2 32766 FOREVER
提示
对于100%的数据满足:0 <= A, B, C < 2k,1 <= k <= 32。
这个题表意不明确,其实就是 x*c=(b-a)(mod 2的k次幂)一个拓展欧几里得就过了,大水题一枚
ll exgcd(ll a,ll b,ll &x,ll &y){ if(b==0){ x=1;y=0;return a; } ll ans=exgcd(b,a%b,x,y); ll t=x; x=y; y=t-a/b*y; return ans; } ll cal(ll a,ll b,ll c){ ll x,y; ll gcd=exgcd(a,b,x,y); if(c%gcd)return -1; x*=c/gcd; b/=gcd; b=abs(b); ll ans=x%b; while(ans<=0)ans+=b; return ans; }
第二题是培训的时候的题,数据稍微加强。不说了就。
本OJ资源来自于互联网,如有侵权请来信告知,friendi@163.com邮箱
问题 C: 数论好题
题目描述
给定A,B,求A^B的所有因数的和,再MOD 9901
输入
一行两个整数 A 和 B。
输出
一行,一个整数
样例输入
2 3
样例输出
15
提示
对于100%的数据满足:0 <= A,B <= 50000000
对于这道题,首先要知道,一个数的所有因数的和表示形式
若A=p1^a1*p2^a2*....*pn^an;
则他的所有因数之和可表示为(1+p1+p1^2+...+p1^a1)*(1+p2+...+p2^a2)*.....*(1+pn+..+pn^an)
也就是说,求n个等比数列的乘机(证明只要排列组合一下)
A^B只要把a1,a2....an都乘B就可以了;
最后利用等比数列求和公式就可以了。
#define ll long long #define mod 9901 ll power(ll a,ll b){ if(b==0)return 1; else if(b&1)return power(a*a%mod,b>>1)*a%mod; else return power(a*a%mod,b>>1)%mod; } int p[10001],cnt,f[10001]; void getp(ll m){ f[1]=1; for(int i=2;i<=sqrt(m);i++){ if(!f[i])p[++cnt]=i; for(int j=i+1;i*j<=sqrt(m);j++){ f[i*j]=1; } } } int main(){ ll a,b; int k=0; cin>>a>>b; getp(a);ll ans=1,pc=0; for(int i=1;i<=cnt;i++){ if(a%p[i]==0){ while(a%p[i]==0){ pc++;a/=p[i]; } pc*=b; //pc%=(mod-1); ans=(ans*(power(p[i],pc+1)-1)*power(p[i]-1,mod-2))%mod; } pc=0; } if(a!=1){ ans=(ans*(power(a,b+1)-1)*power(a-1,mod-2))%mod; }
问题 E: 数论good
题目描述
远古时期文字总个数为N。某个朝代文字恰好为远古时期的k分之一,其中k是N的一个正约数(可以是1和N)。不过具体是哪k分之一,以及k是多少,由于历史过于久远,已经无从考证了。只要符合文献,每一种能整除N的k都是有可能的。一个研究者打算考虑到所有可能的k。显然当k等于某个定值时,该朝的文字个数为N / k。然而从N个文字中保留下N / k个的情况也是相当多的。研究者预计,如果所有可能的k的所有情况数加起来为P的话,那么他研究古代文字的代价将会是G的P次方。 现在他想知道研究古代文字的代价是多少。答案除以999911659的余数。
输入
有且仅有一行:两个数N、G,用一个空格分开。
输出
有且仅有一行:一个数,表示答案除以999911659的余数。
样例输入
4 2
样例输出
2048
提示
对于100%的数据满足:
10%的数据中,1 <= N <= 50;
20%的数据中,1 <= N <= 1000;
40%的数据中,1 <= N <= 100000;
100%的数据中,1 <= G <= 1000000000,1 <= N <= 1000000000。
中国剩余定理
ll crt(){ ll m=1; ll x,y,d,ans=0; for(int i=0;i<=3;i++)m*=w[i]; for(int i=0;i<=3;i++){ d=m/w[i]; exgcd(d,w[i],x,y); ans=(ans+d*a[i]*x)%m; //cout<<d<<endl; } while(ans<=0)ans+=m; return ans; }
问题 D: [SDOI2009]SuperGCD
题目描述
Sheng bill有着惊人的心算能力,甚至能用大脑计算出两个巨大的数的GCD(最大公约 数)!因此他经常和别人比赛计算GCD。有一天Sheng bill很嚣张地找到了你,并要求和你比 赛,但是输给Sheng bill岂不是很丢脸!所以你决定写一个程序来教训他。
输入
共两行: 第一行:一个数A。 第二行:一个数B。
输出
一行,表示A和B的最大公约数。
样例输入
12
54
样例输出
6
提示
对于20%的数据,0 < A , B ≤ 10 ^ 18。
对于100%的数据,0 < A , B ≤ 10 ^ 10000。
这道恶心的高精度题恶心了我好久,最后发现读入错了。。。压位的时候要注意第一位要特判。
GCD(A,B)=2GCD(A/2,B/2)
GCD(A,B)=GCD(A/2,B)=GCD(A,B/2)
GCD(A,B)=GCD(A-B,B)
#include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<cstdio> #include<queue> using namespace std; //unsigned long long a1[1002],b1[1002],ans=0;int k=1,l=1;long long mod=10000000000; #define ll long long #define mod 1000000000ll ll ans=0,k=1,l=1; ll a1[2002],b1[2002]; bool pd(){ int i; for(i=1;i<=max(l,k);i++){ if(a1[i]!=b1[i])return 0; } return 1; } void jian(){ int i=1; while(i<=l||i<=k){ if(a1[i]<b1[i]){ a1[i]+=mod; a1[i+1]--; } a1[i]-=b1[i]; i++; } } void diva(){ for(int i=k;i>1;i--){ a1[i-1]+=(a1[i]%2)*mod; a1[i]/=2; } a1[1]/=2; } void divb(){ for(int i=l;i>1;i--){ b1[i-1]+=(b1[i]%2)*mod; b1[i]/=2; } b1[1]/=2; } void gcd(){ if(pd())return ; while(a1[1]%2==0){diva();} while(b1[1]%2==0){divb();} if(pd())return ; while(a1[k]==0)k--; while(b1[l]==0)l--; int i=max(k,l); while(a1[i]==b1[i])i--; if(a1[i]>b1[i])jian(); else { for(;i>=1;i--)swap(a1[i],b1[i]);swap(k,l);jian();} gcd(); } int main(){ char a[10001],b[10001]; scanf("%s%s",a,b); int lena=strlen(a); int lenb=strlen(b); //memset(a1,0,sizeof(a1)); //memset(b1,0,sizeof(b1)); for(int i=lena-1,t=1;i>=0;i--,t*=10){ if((lena-i-1)%9==0&&lena-i-1){ k++;t=1; } ll x=a[i]-'0'; a1[k]+=x*t; } for(int i=lenb-1,t=1;i>=0;i--,t*=10){ if((lenb-i-1)%9==0&&lenb-i-1){ l++;t=1; } ll x=b[i]-'0'; b1[l]+=x*t; } //for(int i=l;i>=1;i--)cout<<b1[i]; while(a1[1]%2==0&&b1[1]%2==0){ diva(); divb(); ans++; } gcd(); for(int i=1;i<=ans;i++){ for(int j=k;j>=1;j--){ a1[j]*=2; a1[j+1]+=a1[j]/mod; a1[j]%=mod; } if(a1[k+1]>0)k++;} while(a1[k]==0)k--; cout<<a1[k]; k--; for(;k>=1;k--)printf("%09d",a1[k]); return 0; }