比赛地址
ACdream原创群赛の数树
求递推数列的a[a[a[a[n]]]]
方法是暴力。。。
一开始用一个暴力的代码(复杂度 O(n))跑 1min 左右跑出来 a[n] 对于 1e9+7 的循环节 222222224LL , 然后继续跑出来 222222224LL 的循环节 183120LL 然后跑出来 183120LL 的循环节 240LL。于是整个问题就简单了, 矩阵快速幂算出第n位mod 240 , 然后再改mod 为 183120LL ,然后再改成 222222224LL ,然后再改成 1e9 + 7..
(偷懒暴力代码也用矩阵写的。。。)
/* * ===================================================================================== * * Author: KissBuaa.DS(AC) * Company: BUAA-ACMICPC-Group * * ===================================================================================== */ #include <stdio.h> #include <stdlib.h> #include <string.h> //#include <stdbool.h> #include <math.h> #define LL long long #define CLR(x) memset(x,0,sizeof(x)) #define typec LL #define sqr(x) ((x)*(x)) #define abs(x) ((x)<0?(-(x)):(x)) #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) #define PI acos(-1.0) #define lowbit(x) ((x)&(-(x))) #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 #define inf 100000000 //For C++ #include <cctype> #include <algorithm> #include <vector> #include <map> #include <set> #include <queue> #include <stack> #include <bitset> #include <list> #include <iostream> using namespace std; const double eps=1e-10; int dblcmp(typec d) { if (fabs(d)<eps) return 0; return (d>0)?1:-1; } LL modo; const int maxn=3; class Mat { public: LL Matn,Matm; typec a[maxn][maxn]; Mat() { Matn=0; Matm=0; memset(a,0LL,sizeof(a)); } void output(); void init(); void initI(); Mat mul(const Mat &a); Mat power(const Mat&a,LL k); }; void Mat::output() { for (int i=0;i<Matn;++i) { for (int j=0;j<Matm;++j) { if (j!=0) printf(" "); printf("%I64d",a[i][j]); } printf("\n"); } } void Mat::init() { Matn=0; Matm=0; memset(a,0LL,sizeof(a)); } Mat Mat::mul(const Mat &A) { Mat c; c.init(); c.Matn=Matn; c.Matm=A.Matm; for (int i=0;i<Matn;++i) for (int j=0;j<A.Matm;++j) { for (int k=0;k<Matm;++k) { c.a[i][j]=(c.a[i][j]+(a[i][k]*A.a[k][j])%modo)%modo; } } return c; } void Mat::initI() { memset(a,0LL,sizeof(a)); for (int i=0;i<Matn;++i) a[i][i]=1LL; } Mat Mat::power(const Mat& a,LL k) { Mat c=a,b; b.init(); b.Matn=a.Matn;b.Matm=a.Matm; b.initI(); while (k) { if (k & (1LL)) b=b.mul(c); c=c.mul(c); k>>=1LL; } return b; } Mat A ,B; LL g(LL x){ //Mat A; if (x == 0LL) return 0LL; if (x == 1LL) return 1LL; //A.init(); //A.Matn = 1LL , A.Matm = 2LL; //A.a[0][0]=1LL,A.a[0][1]=0LL; //Mat B; B.init(); B.Matn = 2LL , B.Matm = 2LL; B.a[0][0]= 3LL, B.a[1][0]=1LL; B.a[0][1] = 1LL; B.a[1][1]=0LL; B = B.power(B , x - 1LL); //A = A.mul(B); return B.a[0][0]; } LL n; set< pair<LL , LL> > has; #define MP make_pair void solve(){ has.clear(); LL i; LL pre = g(1); for (i = 2 ; ; ++i){ LL res = g(i); if(has.find( MP(pre , res) ) != has.end()){ cout<<i - 2<<endl; return; } has.insert( MP(pre , res) ); pre = res; } } int main(){ modo = 1e9 + 7; solve(); // freopen("0.in" , "r" , stdin); // freopen("0.out" , "w" , stdout); // int T; // cin >> T; // while (T--) solve(); // while(~scanf("%I64d" , &n)) solve(); }
于是得到了这个之后就能用
/* * ===================================================================================== * * Author: KissBuaa.DS(AC) * Company: BUAA-ACMICPC-Group * * ===================================================================================== */ #include <stdio.h> #include <stdlib.h> #include <string.h> //#include <stdbool.h> #include <math.h> #define LL long long #define CLR(x) memset(x,0,sizeof(x)) #define typec LL #define sqr(x) ((x)*(x)) #define abs(x) ((x)<0?(-(x)):(x)) #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) #define PI acos(-1.0) #define lowbit(x) ((x)&(-(x))) #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 #define inf 100000000 //For C++ #include <cctype> #include <algorithm> #include <vector> #include <map> #include <set> #include <queue> #include <stack> #include <bitset> #include <list> #include <iostream> using namespace std; const double eps=1e-10; int dblcmp(typec d) { if (fabs(d)<eps) return 0; return (d>0)?1:-1; } LL modo; const int maxn=3; class Mat { public: LL Matn,Matm; typec a[maxn][maxn]; Mat() { Matn=0; Matm=0; memset(a,0LL,sizeof(a)); } void output(); void init(); void initI(); Mat mul(const Mat &a); Mat power(const Mat&a,LL k); }; void Mat::output() { for (int i=0;i<Matn;++i) { for (int j=0;j<Matm;++j) { if (j!=0) printf(" "); printf("%I64d",a[i][j]); } printf("\n"); } } void Mat::init() { Matn=0; Matm=0; memset(a,0LL,sizeof(a)); } Mat Mat::mul(const Mat &A) { Mat c; c.init(); c.Matn=Matn; c.Matm=A.Matm; for (int i=0;i<Matn;++i) for (int j=0;j<A.Matm;++j) { for (int k=0;k<Matm;++k) { c.a[i][j]=(c.a[i][j]+(a[i][k]*A.a[k][j])%modo)%modo; } } return c; } void Mat::initI() { memset(a,0LL,sizeof(a)); for (int i=0;i<Matn;++i) a[i][i]=1LL; } Mat Mat::power(const Mat& a,LL k) { Mat c=a,b; b.init(); b.Matn=a.Matn;b.Matm=a.Matm; b.initI(); while (k) { if (k & (1LL)) b=b.mul(c); c=c.mul(c); k>>=1LL; } return b; } Mat A ,B; LL g(LL x){ //Mat A; if (x == 0LL) return 0LL; if (x == 1LL) return 1LL; //A.init(); //A.Matn = 1LL , A.Matm = 2LL; //A.a[0][0]=1LL,A.a[0][1]=0LL; //Mat B; B.init(); B.Matn = 2LL , B.Matm = 2LL; B.a[0][0]= 3LL, B.a[1][0]=1LL; B.a[0][1] = 1LL; B.a[1][1]=0LL; B = B.power(B , x - 1LL); //A = A.mul(B); return B.a[0][0]; } LL n; void solve(){ scanf("%lld", &n); LL res; //printf("%I64d\n",g(42837)); modo = 240LL; res = g(n); modo = 183120LL; res = g(res); //res = (res * inv(res , modo))% modo; //cout<<res<<endl; modo = 222222224LL; res = g(res); //cout<<res<<endl; //res = (res * inv(res , modo))% modo; modo =(1000000000LL + 7LL); res = g(res); //res = (res * inv(res-1LL , modo))% modo; //printf("%I64d\n",g(g(g(n)))); printf("%lld\n",res); }/* set< pair<LL , LL> > has; #define MP make_pair void solve(){ has.clear(); LL i; LL pre = g(1); for (i = 2 ; ; ++i){ LL res = g(i); if(has.find( MP(pre , res) ) != has.end()){ cout<<i - 2<<endl; return; } has.insert( MP(pre , res) ); pre = res; } } */ int main(){ // modo = 12LL; //// solve(); // freopen("0.in" , "r" , stdin); // freopen("0.out" , "w" , stdout); int T; cin >> T; while (T--) solve(); // while(~scanf("%I64d" , &n)) solve(); }
这题比较贱的是我故意选择了答案是 0 和 1 的答案,发现好多啊。。。
这是个原题,我觉得太好玩儿了就拿过来了。。。
求 abs(x - y)
longlong 的 x - y 会溢出,所以只要特判加起来是 2 ^ 63 的两种情况即可。。。。
void solve(){ LL a , b; RD(a , b); if (a == 4611686018427387904ll && b == -4611686018427387904ll) printf("9223372036854775808\n"); else if (b == 4611686018427387904ll && a == -4611686018427387904ll) printf("9223372036854775808\n"); else OT(abs(a - b)); } int main(){ //#ifdef LOCAL // freopen("0.in" , "r" , stdin); // freopen("0.out" ,"w" , stdout); //#endif Rush solve(); }
这题的高精度方法是被我故意卡掉的。。。
求原问题答案 >= n 的最小的数
推出公式 + 二分,公式就是 n ^ 2 - n + 2, 然后特殊判断一下 n = 1 输出 0 的情况即可
LL n; void solve(){ RD(n); if (n == 1){ puts("0"); return; } LL low = 1 , high = 1e5 , mid , ret = high; do{ mid = low + high >> 1; if (mid * mid - mid + 2 >= n){ checkMin(ret , mid); high = mid - 1ll; } else low = mid + 1ll; }while(low <= high); OT(ret); } int main(){ // freopen("0.in" , "r" , stdin); // freopen("0.out" , "w" , stdout); Rush solve(); }
这题准备和 CF #173 E 一起讲。
求一个数在一堆数选一个数,最大的异或值
CF : 求数列不重叠前缀 & 后缀 最大异或值
用Trie 或者手写二叉树,来记录每个数字的每一个二进制位。
试想,对于一个数字x,在ai里面找最大的异或值,其实就是一个贪心的过程:
1、把x每一位取反(0->1 , 1 -> 0)
2、从最高位开始找,如果最高位和x取反的最高位相等,那么异或值的最高位就是 1 , 如果没有的话只能是 0 了。
3、不停滴做 2,于是就是在二叉树 / Trie 上面尽可能找和 1 之后的x尽量“匹配”的数字即可。
复杂度理论是O(n)
struct node{ int son[2] , value; void reset(){ son[0] = -1 , son[1] = -1 , value = -1; } }tree[32 * 10000]; int id; int mm[32]; int dig[32]; char op[10]; void getdig(int x , int rev){ for (int i = 0 ; i < 32 ; ++i) dig[i] = ((x & mm[31 - i]) != 0) ^ rev; } void insert(int x){ getdig(x , 0); int root = 0; for (int i = 0 ; i < 32 ; ++i){ if (tree[root].son[dig[i]] == -1){ tree[root].son[dig[i]] = ++id; tree[id].reset(); } root = tree[root].son[dig[i]]; } tree[root].value = x; } int query(int x , int rev){ getdig(x , rev); int root = 0; for (int i = 0 ; i < 32 ; ++i){ // OT(dig[i]); if (tree[root].son[dig[i]] == -1) root = tree[root].son[(dig[i] ^ 1)]; else root = tree[root].son[dig[i]]; } return x ^ tree[root].value; } void solve(){ id = 0; tree[0].reset(); Rush{ RS(op); if (op[0] == 'i') insert(RD()); else OT(query(RD() , op[2] == 'a')); } } void init(){ REP(i , 32) mm[i] = 1 << i; } int main(){ init(); Rush solve(); }
这题暴力是绝对不可能通过的,我跑了 5.5 h。。。。
这题的数据结构和上面的一样只不过建立不太相同
1、首先 1 ~ n 枚举 前 i 个数的异或值
2、将树情况,插入 0
3、从 n -> 1 枚举,每次i前缀异或值 在树中查找 max , 记录 ; 然后将后缀异或值 插入树,并且将后缀异或值 和 max 进行比较。
那么一趟下来之后,也就是枚举了每个前缀(包括空)对于不重叠后缀们的异或最大值。
http://codeforces.com/contest/282/submission/3311133
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const double pi=acos(-1); int t,l,a; double x,b; int main(){ scanf("%d",&t); while (t--){ scanf("%d%d",&l,&a); b=(90-a%90)*pi/180; x=l/(1+sin(b)+cos(b)); //xsinb+x+xcosb=l printf("%.2f\n",l*l-x*x*sin(2*b)); } return 0; }
int f[100][4] , num[100]; int new_s(int s , int d){ if (d == 3) return s | 1; if (d == 8) return s | 2; return s; } int dfs(int i, int s, bool e) { if (i==-1) return s==1 || s == 2; if (!e && ~f[i][s]) return f[i][s]; int res = 0; int u = e?num[i]:9; for (int d = 0; d <= u; ++d) res += dfs(i-1, new_s(s, d), e&&d==u); return e?res:f[i][s]=res; } int gao(int x){ int m = 0; while(x){ num[ m++ ] = x % 10; x /= 10; } return dfs(m - 1 , 0 , 1); } void solve(){ int l , r; RD(l , r); OT(gao(r) - gao(l - 1)); } int main(){ // freopen("0.in" , "r" , stdin); // freopen("0.out" , "w" , stdout); FLC(f , -1); Rush solve(); }