前言:今天参加某谷的比赛,蒟蒻自闭,没远大追求回的我去搞基础,其实出题人发了题解,主要总结得失.
T1:给定一串数,分组求异或和,ans=Σ分组异或和,求ans最大.
S1:之前做过区间求异或和,开始以为是线段树,想了一下,将数二进制拆分,发现将数一个个异或就是答案.不会证明,但感性理解一下,发现分组的目就是尽可能将同位置的'1'抵消,一个个异或看似没分组,实际已将可能的同位置'1'抵消,严谨证明看题解吧.
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; #define e exit(0) #define re register int n,ans,val[1000010]; int main() { freopen("T1.in","r",stdin); freopen("T1.out","w",stdout); scanf("%d",&n); for(re int i=1;i<=n;++i) scanf("%d",&val[i]); for(re int i=1;i<=n;++i){ if(i==1) ans=val[i]; else ans^=val[i]; } printf("%d",ans); return 0; }
T2:给定实数:n,a,b,设ans = floor( pow( n , a ) + pow( n , b ) ).设有n'∈[L,R],使ans'=floor(pow( n' , a ) + pow(n' , b) ) = ans.设len = Rmax - Lmin,给定q组询问,求Σlen.
S2:二分答案拿走65pts.
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; int T,seed,op; long long st; double n,a,b,ans,L,R,l,r; #define e exit(0) namespace Mker { // Powered By Kawashiro_Nitori // Made In Gensokyo, Nihon #define uint unsigned int uint sd;int op; inline void init() {scanf("%u %d", &sd, &op);} inline uint uint_rand() { sd ^= sd << 13; sd ^= sd >> 7; sd ^= sd << 11; return sd; } inline double get_n() { double x = (double) (uint_rand() % 100000) / 100000; return x + 4; } inline double get_k() { double x = (double) (uint_rand() % 100000) / 100000; return (x + 1) * 5; } inline void read(double &n,double &a, double &b) { n = get_n(); a = get_k(); if (op) b = a; else b = get_k(); } } inline int fd() { int s=1,t=0; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') s=-1; c=getchar(); } while(c>='0'&&c<='9'){ t=t*10+c-'0'; c=getchar(); } return s*t; } bool check1(double x) { long long as=floor(pow(x,a)+pow(x,b)); if(as<=st) return true; else if(as>st) return false; } bool check2(double x) { long long as=floor(pow(x,a)+pow(x,b)); if(as>=st) return true; else if(as<st) return false; } int main() { freopen("T2.in","r",stdin); freopen("T2.out","w",stdout); T=fd(); Mker::init(); while(T--){ Mker::read(n,a,b); st=floor(pow(n,a)+pow(n,b)); l=n-1.0,r=n+1.0; while(abs(r-l)>1e-10){ double mid=(l+r)/2; if(check1(mid)) l=mid; else r=mid; } R=l; l=n-1.0,r=n+1.0; while(abs(r-l)>1e-10){ double mid=(l+r)/2; if(check2(mid)) r=mid; else l=mid; } L=l; ans+=(R-L); } printf("%lf",ans); return 0; }
T4:已知a0 = -3 , a1 = -6 , a2 = -12 ,an = 3an-1 + an-2 - 3an-3 + pow( 3 , n ).求ans.
S4:显然递推超时,尝试构造矩阵快速幂,无奈题目毒瘤800ms,(还以为997ms卡过了)
初始矩阵:[ a0 , a1 , a2 , 27 ].
转移矩阵:[ 0 , 0 , -3 , 0 ]
[ 1 , 0 , 1 , 0 ]
[ 0 , 1 , 3 , 0 ]
[ 0 , 0 , 1 , 3 ]
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define e exit(0) #define re register const int mod=1e9+7; int T; long long n; namespace Mker { // Powered By Kawashiro_Nitori // Made In Gensokyo, Nihon #include<climits> #define ull unsigned long long #define uint unsigned int ull sd;int op; inline void init() {scanf("%llu %d", &sd, &op);} inline ull ull_rand() { sd ^= sd << 43; sd ^= sd >> 29; sd ^= sd << 34; return sd; } inline ull rand() { if (op == 0) return ull_rand() % USHRT_MAX + 1; if (op == 1) return ull_rand() % UINT_MAX + 1; if (op == 2) return ull_rand(); } } inline int fd() { int x=0;int f(0);char ch(getchar()); while(!isdigit(ch)) f|=(ch=='-'),ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return x=f?-x:x; } struct jz{ int a[10][10]; jz(){memset(a,0,sizeof(a));} jz operator*(const jz p){ jz ans; for(re int k=1;k<=4;++k) for(re int i=1;i<=4;++i) for(re int j=1;j<=4;++j) ans.a[i][j]=((ans.a[i][j]%mod+(1ll*a[i][k]*p.a[k][j])%mod)%mod+mod)%mod; return ans; } }; jz work() { jz g; g.a[1][1]=0,g.a[2][1]=1,g.a[3][1]=0,g.a[4][1]=0; g.a[1][2]=0,g.a[2][2]=0,g.a[3][2]=1,g.a[4][2]=0; g.a[1][3]=-3,g.a[2][3]=1,g.a[3][3]=3,g.a[4][3]=1; g.a[1][4]=0,g.a[2][4]=0,g.a[3][4]=0,g.a[4][4]=3; return g; } jz qsm(jz k,int y) { jz ans; for(re int i=1;i<=4;++i) ans.a[i][i]=1; while(y){ if(y&1) ans=ans*k; k=k*k; y>>=1; } return ans; } int a0=-3,a1=-6,a2=-12,x=27,ans; int main() { freopen("T3.in","r",stdin); freopen("T3.out","w",stdout); T=fd(); Mker::init(); while(T--){ n=Mker::rand(); jz k; k=work(); k=qsm(k,n-2); int sum=0; for(re int i=1;i<=4;++i){ if(i==1) sum=((sum%mod+1ll*a0*k.a[1][3]%mod)%mod+mod)%mod; else if(i==2) sum=((sum%mod+1ll*a1*k.a[2][3]%mod)%mod+mod)%mod; else if(i==3) sum=((sum%mod+1ll*a2*k.a[3][3]%mod)%mod+mod)%mod; else if(i==4) sum=((sum%mod+1ll*x*k.a[4][3]%mod)%mod+mod)%mod; } if(ans==0) ans=sum; else ans^=sum; } printf("%d",ans); return 0; }
可能对当前水平能做的只有这么多,别放弃拿分!
附上:题解.