A.斐波拉契
求$f[n-1]*f[n+1]-f[n]^2$,$f[n]$为斐波拉契数列第$n$项
算一下前几项不难发现答案为$(-1)^n$,下面用数学归纳法证明一下:
$n=2$时,猜想成立
假设$n=k$时猜想成立,即$f[k-1]*f[k+1]-f[k]^2=(-1)^k$
当$n=k$时,$f[k]f[k+2]-f[k+1]^2=f[k]
得证
#include <cstdio> #include <algorithm> #include<vector> #include<iostream> #include<cstring> char s[1000005]; using namespace std; int main(){ scanf("%s",s); int l=strlen(s); int z=s[l-1]-'0'; if(z%2==0) cout<<1<<endl; else cout<<-1<<endl; }
#include <cstdio> #include <algorithm> #include<vector> #include<iostream> using namespace std; bool vis[10005]; int a[10005]; vector<int> ans; int main(){ long long a,b; cin>>a>>b; cout<<a+b<<endl; }
C.序列
暴力就好,先求出该序列每处的前缀和,用map表示该前缀和存在,对于每次查询,先判断k之前是否查询过,查询过则不用判断,再判断序列和是否是k的倍数,否则,对于$1(sum/z)~k(sum/z)$的前缀和是否都存在
#include <cstdio> #include <algorithm> #include<vector> #include<iostream> #include<cstring> #include<map> using namespace std; typedef long long ll; const int maxn=100005; int ans[maxn]; ll a[maxn]; map<ll,int> mp; int main(){ int n,q; scanf("%d%d",&n,&q); ll sum=0; for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); sum+=a[i]; mp[sum]=1; } for(int i=1;i<=q;i++){ int z; scanf("%d",&z); if(z>n||sum%z!=0||ans[z]==2){ printf("No "); continue; } if(ans[z]==1){ printf("Yes "); continue; } for(int i=1;i*(sum/z)<sum;i++){ if(mp[i*(sum/z)]!=1){ printf("No "); ans[z]=2; break; } } if(ans[z]!=2){ printf("Yes "); ans[z]=1; } } }
求下直径就好了
#include <cstdio> #include <algorithm> #include<vector> #include<iostream> #include<cstring> using namespace std; const int maxn=100005; vector< pair<int,int> > g[maxn]; int d[maxn]; bool vis[maxn]; void dfs(int u){ vis[u]=1; for(int i=0;i<g[u].size();i++){ int v=g[u][i].first; if(!vis[v]){ d[v]=d[u]+g[u][i].second; dfs(v); } } } int main(){ int n; scanf("%d",&n); for(int i=1;i<n;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); g[x].push_back(make_pair(y,z)); g[y].push_back(make_pair(x,z)); } // cout<<-1<<endl; dfs(1); int cnt; long long dmax=0; for(int i=1;i<=n;i++){ if(d[i]>dmax){ dmax=d[i]; cnt=i; } vis[i]=0; d[i]=0; } dmax=0; dfs(cnt); for(int i=1;i<=n;i++){ if(d[i]>dmax){ dmax=d[i]; } } cout<<dmax*10+(1+dmax)*dmax/2<<endl; }
E.旅行青蛙
最长上升子序列,但是感觉题意有问题,题目的描述应该是最长不上升子序列233,n比较大,用$O(n*log n)$的写法
#include <cstdio> #include <algorithm> #include<vector> #include<iostream> #include<cstring> using namespace std; const int maxn=100005; int dp[maxn]; int a[maxn]; int n; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int cnt=0; dp[0]=-1e9; for(int i=1;i<=n;i++){ if(a[i]>=dp[cnt]){ dp[++cnt]=a[i]; } else { int z=upper_bound(dp+1,dp+1+cnt,a[i])-dp; dp[z]=a[i]; } } cout<<cnt<<endl; }
F.子序列
由题意知,答案与序列的顺序无关,故先将序列排个序,对于序列中的第i个数,需要相乘的次数为$C{n-1}^{k-1}-C{i-1}^{k-1}-C_{n-i}^{k-1}$。又1e9+7为素数,根据欧拉公式$a^{p-1}equiv1mod p$
即可得出答案
#include <cstdio> #include <algorithm> #include<vector> #include<iostream> #include<cstring> #include<map> using namespace std; typedef long long ll; const ll mod=1e9+7; const int maxn=1005; ll pmod(ll a,ll b){ if(a==0) return 0; if(b==0) return 1; if(b==1) return a%mod; ll ans=pmod(a,b/2); ans=ans*ans%mod; if(b&1) return ans*a%mod; return ans; } ll a[maxn]; ll c[maxn][maxn]; int main(){ for(int i=0;i<=1000;i++) c[i][0]=1; c[1][1]=1; for(int i=1;i<=1000;i++) c[i][i]=1; for(int i=1;i<=1000;i++) for(int j=1;j<i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%(mod-1); int t; scanf("%d",&t); while(t--){ int n,k; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); sort(a+1,a+1+n); ll ans=1; for(int i=2;i<n;i++){ ll z=c[n-1][k-1]; if(n-i>=k-1) z-=c[n-i][k-1]; if(i-1>=k-1) z-=c[i-1][k-1]; z=((z)%(mod-1)+mod-1)%(mod-1); z=pmod(a[i],z); ans=ans*z%mod; } printf("%lld ",ans); } return 0; }