Project Euler 1-25
A. Multiples of 3 and 5
大水题,计算出below n内是3,5倍数的总和
数据较大,只能用求和公式
#include <iostream> #include <cstdio> typedef long long ll; using namespace std; int main() { int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); ll sum=0; ll p; p = (n-1)/3; sum += (1LL)*3*(p+1)*p/2; p = (n-1)/5; sum += (1LL)*5*(p+1)*p/2; p = (n-1)/15; sum -= (1LL)*15*(p+1)*p/2; cout<<sum<<endl; } //cout << "Hello world!" << endl; return 0; }
B.Even Fibonacci numbers
求出n以内所有偶数的总和
所有偶数都是3个一循环出现,序列为0,2,8,34,144...
发现规律E【i】 = 4*E【i-1】+E【i-2】
打表计算
#include <iostream> #include <cstdio> typedef long long ll; using namespace std; const int MAXN = 1e3+100; const ll MAXNN = 4e16; ll a[MAXN]; ll sum[MAXN]; ll top; int main() { a[0] = 0; a[1] = 2; sum[0] = 0; sum[1] = 2; for(ll i=2;;i++){ a[i] = 4*a[i-1]+a[i-2]; top ++; sum[i] = sum[i-1]+a[i]; //cout<<top<<endl; if(a[i]>MAXNN)break; } top+=2; //cout<<a[2]<<a[3]<<" "<<a[4]<<endl; int T; scanf("%d",&T); while(T--){ ll n; scanf("%lld",&n); int l=0,r=top; while(l<r){ int m = l+(r-l)/2; if(a[m]<=n)l = m+1; else r = m; } printf("%lld\n",sum[l-1]); } //cout << "Hello world!" << endl; return 0; }
http://digi.tech.qq.com/a/20150526/008620.htm
我发现这个fib时钟挺好玩的
时钟:红色+蓝色
分钟:(绿色+蓝色)*5
C. Largest prime factor
求最大质因子
prime打表,昨天打了bc,去求了最大因子,呵呵
#include <iostream> #include <cstdio> typedef long long ll; using namespace std; const int MAXN = 1e7+1000; //const ll MAXNN = 4e16; int visit[MAXN]; ll p[MAXN]; ll cnt; void isprime(){ cnt = 0; for(ll i=2;i<MAXN;i++){ if(!visit[i]){ p[cnt++] = i; for(ll j=i*2;j<MAXN;j+=i){ visit[j] = 1; } } } } int main() { isprime(); //cout<<p[1]<<endl; //cout<<p[2]<<endl; int T; scanf("%d",&T); while(T--){ ll n; scanf("%lld",&n); // cout<<n<<endl; ll mmax = -1; for(ll i=0;i<cnt;i++){ if(n%p[i]==0){ mmax = max(mmax,p[i]); while(n%p[i]==0)n/=p[i]; } } if(n>1){ mmax = max(mmax,n); } cout<<mmax<<endl; // cout<<n<<endl; } return 0; }
H.Largest product in a series
求k个连续序列最大值
遍历的时候考虑前一个序列的第一个值是否为0
#include <cstdio> #include <iostream> #include <cstring> #include <string> using namespace std; const int MAXN = 1e3+100; char ts[MAXN]; int main(){ int T; scanf("%d",&T); while(T--){ int n,k; scanf("%d%d",&n,&k); scanf("%s",ts); int len = strlen(ts); int mmax=1; for(int i=0;i<k;i++)mmax *= (ts[i]-'0'); int pre = mmax; //cout<<pre<<endl; for(int i=k;i<len;i++){ //pre = pre/(ts[i-k]-'0')*(ts[i]-'0'); if(ts[i-k]-'0'==0){ pre = 1; int s = i-k+1; for(int j=1;j<=k;j++){ pre *= (ts[s++]-'0'); } }else{ pre = pre*(ts[i]-'0')/(ts[i-k]-'0'); } mmax = max(mmax,pre); //cout<<pre<<endl; } cout<<mmax<<endl; } return 0; }
I.Special Pythagorean triplet
求构成勾股数的abc,乘积最大
一眼看成求最小,测试数据能过,又傻逼了,改了一个小时看不出,差点要哭
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> typedef long long ll; using namespace std; const ll MAXN = 3e3+100; ll p[MAXN]; int main() { //memset(p,-1,sizeof p); for(int i=1;i<MAXN/3;i++){ for(int j=i+1;j<MAXN/2;j++){ ll t = (1LL)*i*i + (1LL)*j*j; ll x = sqrt(t); if(t==x*x&&j<x&&i+j+x<MAXN){ if(p[i+j+x]==0) p[i+j+x] = (1LL)*i*j*x; else p[i+j+x] = max(p[i+j+x],(1LL)*i*j*x); } } } int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); if(p[n]==0){ cout<<-1<<endl; continue; } cout<<p[n]<<endl; } //cout << "Hello world!" << endl; return 0; }
L.Highly divisible triangular number
这个挺坑的,反正思路挺清晰的,n的所有因子总数是 (1+a1)*(1+a2)*(1+a3)...(ai为n的质因子)
至于为什么坑了那么久,就是因为打表的时候,我数组我不敢开太大,orz
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cmath> typedef long long ll; using namespace std; const int MAXN = 1e4; const int MAXNN = 1e6; int vis[MAXN]; int p[MAXN]; int cnt; ll s[MAXNN]; ll num[MAXNN]; int top; void isprime(){ cnt= 0; for(int i=2;i<MAXN;i++){ if(!vis[i]){ p[cnt++] = i; for(int j=2*i;j<MAXN;j+=i){ vis[j] = 1; } } } } int main() { isprime(); top = 1; for(int i=1;i<MAXNN;i++)s[i] = s[i-1]+i; //cout<<s[MAXNN-1]<<endl; for(int i=1;i<MAXNN;i++){ ll t = s[i]; ll k = 0; ll sum=1; for(int j=0;j<cnt&&p[j]<=sqrt(t);j++){ k=0; if(t%p[j]==0){ while(t%p[j]==0){ t/=p[j]; k++; } sum *= (k+1); } } if(t>1)sum *= 2; num[i] = sum; top++; if(sum>1000){ break; } //cout<<sum<<endl; } // cout<<top<<endl; //cout<<num[top-1]<<endl; //cout<<s[top-1]<<endl; int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); ll ans=-1; for(int i=1;i<=top;i++){ if(num[i]>n){ ans = s[i]; //cout<<i<<endl; break; } } cout<<ans<<endl; } //cout << "Hello world!" << endl; return 0; }
M.Large sum
大数模板
http://blog.csdn.net/vsooda/article/details/8543351
http://blog.csdn.net/y990041769/article/details/20116995
这些模板都没负数操作的样子。。。
#include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std; string sum(string s1,string s2) { if(s1.length()<s2.length()) { string temp=s1; s1=s2; s2=temp; } int i,j; for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--) { s1[i]=char(s1[i]+(j>=0?s2[j]-'0':0)); //注意细节 if(s1[i]-'0'>=10) { s1[i]=char((s1[i]-'0')%10+'0'); if(i) s1[i-1]++; else s1='1'+s1; } } return s1; } int main() { int n; scanf("%d",&n); string ts1; cin>>ts1; for(int i=1;i<n;i++){ string ts2; cin>>ts2; ts1 = sum(ts1,ts2); } for(int i=0;i<10;i++)cout<<ts1[i]; cout<<endl; //cout << "Hello world!" << endl; return 0; }
N.Longest Collatz sequence
这题很坑
n可能大于int了(奇数为3*n+1),所以这就要开longlong
一天都不知道错在哪里
#include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std; const int MAXN = 5e6+10; typedef long long ll; int a[MAXN],b[MAXN]; int dfs(ll x){ if(x<MAXN&&a[x]){ return a[x]; } int sum = 0; if(x%2==0){ sum = dfs(x/2)+1; }else{ sum = dfs(x*3+1)+1; } if(x<MAXN)a[x] = sum; return sum; } int main() { a[1]=b[1]=1; int mmax = -1; int pre = 1; for(int i=2;i<MAXN;i++){ if(!a[i]) a[i] = dfs(i); if(mmax<=a[i]){ pre = i; mmax = a[i]; } b[i] = pre; } int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); printf("%d\n",b[n]); } //cout << "Hello world!" << endl; return 0; }
O.Lattice paths
简单dp
#include <cstdlib> #include <cstring> #include <iostream> #include <cmath> #include <cstdio> using namespace std; typedef long long ll; const ll mod = 1e9+7; const int MAXN = 5e2+10; ll dp[MAXN][MAXN]; int main(){ for(int i=1;i<MAXN;i++){ for(int j=1;j<MAXN;j++){ if(j==1&&i==1)dp[i][j] = 1; else dp[i][j] = dp[i-1][j]+dp[i][j-1]; dp[i][j] %= mod; } } int T; scanf("%d",&T); while(T--){ int n,m; scanf("%d%d",&n,&m); cout<<dp[n+1][m+1]<<endl; } }
P.Power digit sum
字符串操作
#include <cstdlib> #include <cstring> #include <iostream> #include <cmath> #include <cstdio> using namespace std; typedef long long ll; const ll mod = 1e9+7; const int MAXN = 1e4+100; string ts = "1"; ll a[MAXN]; int main(){ for(int i=1;i<MAXN;i++){ int len = ts.length(); int flag = 0; ll sum = 0; for(int j=len-1;j>=0;j--){ int t = ts[j]-'0'; t = t*2+flag; ts[j] = char(t%10+'0'); flag = t/10; sum += t%10; } if(flag){ ts = "1"+ts; sum += 1; } //cout<<ts<<endl; a[i] = sum; } cout<<ts.length()<<endl; cout<<ts<<endl; int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); cout<<a[n]<<endl; } }
R.Maximum path sum I
简单dp
S.Counting Sundays
计算任意任意区间每月第一天为周七的个数
和省赛一题一模一样,不过好像是求周一的个数,然后我也想当然了,然后第二组测试数据直接出不来。。。
不过学了一个很有用的计算任意时间为周几的 蔡勒公式
http://blog.csdn.net/kumxp/article/details/5185309
#include <iostream> #include <cstdio> #include <cmath> using namespace std; typedef long long ll; /*计算任何日期为周几模板*/ int fun(int x,int y,int z){ if(y<3){ x-=1; y+=12; } int a = x/100,b = x-100*a; int w = a/4 - 2*a+b+b/4+(13*(y+1)/5)+z-1; w = (w%7+7)%7; return w; } int main() { /*for(int i=1;i<13;i++){ cout<<fun(2016,i,1)<<" "; } cout<<endl;*/ int T; scanf("%d",&T); while(T--){ ll tx1;int x1,y1,z1; ll tx2;int x2,y2,z2; scanf("%lld%d%d",&tx1,&y1,&z1); scanf("%lld%d%d",&tx2,&y2,&z2); x1 = (tx1-1900)%400+1900; x2 = (tx2-tx1)+x1; int ans = 0; for(int i=x1;i<=x2;i++){ int ret = 0; int s = 1,e = 13; if(i==x1){ s = y1; if(z1>1)s++; }if(i==x2){ e = y2+1; } for(int j=s;j<e;j++){ if(fun(i,j,1)==0)ret++; } //cout<<ret<<endl; ans += ret; } cout<<ans<<endl; } //cout << "Hello world!" << endl; return 0; }
T.Factorial digit sum
继续套大数相乘模板
U.Amicable numbers
打表的时候注意是否会超出得到的数字是否会超出数组范围
第二次犯这个错误了
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 1e5+1000; int a[MAXN]; ll b[MAXN]; int main() { //ll sum = 0; for(int i=1;i<MAXN;i++){ int t = i; ll cnt = 0; for(int j=2;j<=sqrt(t);j++){ if(t%j==0){ cnt += j; if(j*j!=t)cnt+= t/j; } } cnt++; b[i] = cnt; if(cnt<i&&b[cnt]==i){a[i] = a[cnt] = 1;} else if(cnt>MAXN){ ll k = 0; for(int j=2;j<=sqrt(k);j++){ if(cnt%j==0){ k += j; if(j*j!=cnt)k+= cnt/j; } } k++; if(cnt==k)a[i] = 1; } //cout<<sum<<endl; } //cout<<b[MAXN-20]<<endl; int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); ll ret = 0; for(int i=1;i<=n;i++){ if(a[i])ret+= i; } cout<<ret<<endl; } return 0; }
X.Lexicographic permutations
粗略学习了康托展开
排列组合好像非常有用的样子
http://www.cnblogs.com/xianglan/archive/2011/03/07/1976431.html
http://blog.csdn.net/zhongkeli/article/details/6966805
#include <cstdio> #include <iostream> #include <string> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; ll fac[20]; int sg[20]; int main(){ ll mult = 1; for(int i=1;i<13;i++){ mult *= i; fac[12-i] = mult; } int T; string ts; scanf("%d",&T); while(T--){ ts = "abcdefghijklm"; memset(sg,0,sizeof sg); ll n; scanf("%lld",&n); n--; for(int i=0;i<12;i++){ sg[i] = n/fac[i]; n -= sg[i]*fac[i]; } /*for(int i=0;i<12;i++){ cout<<sg[i]<<" "; } cout<<endl;*/ for(int i=0;i<12;i++){ swap(ts[i],ts[i+sg[i]]); sort(ts.begin()+i+1,ts.end()); } cout<<ts<<endl; } }
Y.N-digit Fibonacci number
求第一次出现5000-digit fibonacci的下标
这题应该能用字符串的大数操作的样子
学习了一种公式的方法
fib数列如果n较大时,满足an/an+1 = 0.618:1
则an*phi = an,phi=(1+sqrt(5))/2
ox = (1-sqrt(5))/2
可以推出an的通式 an = 1/(sqrt(5))*(phi-ox)^n
则len_dig = (int)(nlog10(phi)-log10(5)/2+1)
呵呵,继续学习了fib
#include <cstdio> #include <iostream> #include <string> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const int MAXN = 5e3+10; const int MAXNN = 3e4+100; double golden = (1+sqrt(5))/2; int a[MAXN]; int len_fib(ll n){ return (int)(n*log10(golden) - log10(5)/2+1); } int main(){ //cout<<len_fib(17)<<endl; //ll k = 0; a[1] = 1; for(int i=2;i<MAXN;i++){ int l = 1,r = MAXNN; while(l<r){ int m = l+(r-l)/2; if(len_fib(m)<i)l = m+1; else r = m; } a[i] = l; } /*cout<<a[2]<<endl; cout<<a[3]<<endl; cout<<a[5000]<<endl; cout<<k<<endl;*/ int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); cout<<a[n]<<endl; } return 0; }