zoukankan      html  css  js  c++  java
  • 1110考试总结

    1101 考试总结

    T1

    ​ 题目大意:

    ​ 给定一个不小于2 的整数k ,按照如下方式生成一个无限长的序列S (下标从0 开始)。

    1. 初始时序列只有一个元素S0 = 0 。

    2. 对于 j = 1,2,...,k-1分别把当前序列的每个元素都加上 j ,得到新的k -1个序列。

    3. 把新的k -1个序列依次接在当前序列后面,得到一个长度为当前序列长度k 倍的序列。

    4. 把这个序列每一项都变成其除以k 之后的余数,并把这个序列作为新的当前序列。

    5. 执行无穷次操作 2-4。

    ​ 例如k = 3 ,每一轮执行之后的序列分别是:

    012
    
    012 120 201
    
    012120201 120201012 201012120
    
    ......
    

    例如k = 2 ,则序列是 01101001100101101001011001101001……

    现在给定整数 L, R ,你需要求(displaystyle sum _{i = L} ^{R} h(i) * S_i)的值,并输出答案对(2^{32}) 取模. (h(i) = lfloor frac{(i \% 20000116) ^ 2 + i + 804}{233} floor).

    (T <= 100, 2 <= k <= 1000, L,R <= 1e16, sum R - L <= 1e8).

    思维题.

    我们不考虑模数, 当(k = 3)时候的序列应该就是:0 1 2 1 2 3 2 3 4 ...

    然后我们考虑每个数是怎么来的, 我们把序列分层:

    0
    0 1 2
    012 123 234
    

    最后那个4其实是由上一层的2加上2得到的. 可以发现, 每一层的数字可以分层(k)块, 假设一个数字在第(t)块, 那么它就是由上一层对应数字加上(t - 1)得到的.

    然后我们只需要找到这个数字对应的第(t)块是什么就好了.代码里的(tmp[i])数组就是表示从第i层向第(i + 1)层需要加多少.

    我们先求出(l)(tmp)数组, 然后推出(l + 1)(tmp)数组是什么.

    怎么推呢?看代码里的(inc)函数.

    首先从(tmp[0] ++), 如果说(tmp[0] == k),说明这一层不能继续加了, 就类似于进位一样, 让(tmp[0] = 0, tmp[1] ++).

    好吧我还不透彻

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline long long read() {
    	long long s = 0, f = 1; char ch;
    	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    	return s * f;
    }
    
    int k, s, cnt, tmp[105];
    unsigned ans; //开unsigned自动溢出,就不用取模了
    long long l, r;
    
    unsigned h(long long x) {
    	long long t = x % 20000116;
    	return (t * t + x + 804) / 233;
    }
    	
    void inc() {
    	tmp[0] ++; if(++ s == k) s = 0;
    	for(int i = 0;tmp[i] == k; i++) {
    		tmp[i] = 0; tmp[i + 1] ++;
    		if(++ s == k) s = 0;
    	}
    }
    
    int main() {
    
    	for(int T = read(); T ; T --) {
    		k = read(); l = read(); r = read(); ans = 0; cnt = 0;
    		memset(tmp, 0, sizeof(tmp));
    		for(long long i = l; i ; i /= k) tmp[cnt ++] = i % k;
    		s = 0; for(int i = 0;i < cnt; i++) (s += tmp[i]) %= k;
    		for(long long i = l;i <= r; i++, inc()) ans += h(i) * s;
    		printf("%u
    ", ans);
    	}
    	
    	return 0;
    }
    
    /*
    10
    2 1 10 
    3 1 10 
    4 1 10 
    5 1 10 
    2 1001 5005 
    10 123 456 
    233 1024 6174 
    16 10000 20000 
    20 12345678 23456789 
    987 2333123456789 2333198765432
    */
    

    T4

    (另一套题的T1)

    ​ 题目大意:

    ​ 给定一个(n * m)的棋盘, 然后放两个国际象棋的皇后, 问有多少种方案可以使两个皇后冲突.(n, m <= 1e9),答案对100000007取模.

    题目链接

    ​ 数学, 组合数.

    ​ 对于每一行, 我们可以放的方案数是(n * A_{m}^{2} = n *m * (m - 1)), 对于每一列, 我们可以放的方案数是(m * A_{n}^{2} = m * n * (n - 1)).

    ​ 对于每一斜列, 我们可以....???有点难搞.

    ​ 每条斜线的长度不一样, 我们可以把大的式子写出来(2 * (A_2^2 + A_3^2 + A_4^2+...+ A_n^2 * (m - n + 1) + ... + A_3^2 + A_2^2)).((m >= n), 乘二是因为有左斜线和右斜线)

    ​ 然后我们把括号拆一下:(4 * (1 * 2 + 2 * 3 + 3 * 4 + ... + (n - 1) * n) + 2n(n - 1)(m - n) = displaystyle 4 *sum_{i = 1}^{n - 1} i(i + 1) + 2n(n - 1)(m - n) = 4 * (sum_{i = 1}^{n - 1}i^2 + sum_{i = 1}^{n - 1}i) + 2n(n - 1)(m - n)).

    (displaystyle sum_{i = 1}^{n - 1}i = frac{n(n - 1)}{2}).这个很好理解.那前面那个死个妈怎么搞??

    ​ 首先:(n ^ 3 - (n - 1)^3 = 3n^2 - 3n + 1, (n - 1)^3 - (n - 2)^3 = 3(n - 1)^2 - 3(n - 1) + 1),这个应该很好推.

    ​ 然后:(displaystyle sum_{i = 2}^{n} i^3 - (i - 1)^3 = n ^ 3 - 1^3 = 3(n ^ 2 + (n - 1)^2 + ... + 2^2 + 1^2) - 3(n + n - 1 + n - 2 + ... + 2 + 1) + (n - 1))(注意是(n - 1)).

    ​ 接着移项:(3 * displaystyle sum_{i = 1}^{n} i^2 = n^3 - n + frac{3n(n + 1)}{2}), 所以(displaystyle sum_{i = 1}^{n} i^2 = (n^3 - n + frac{3n(n + 1)}{2})/3) = (frac{2n^3 + 3n^2 + n}{6} = frac{n(n - 1)(2n + 1)}{6}).

    ​ 所以最后总的式子就是:(n * m * (n - 1 + m - 1) + 2 * n * (n - 1) * (3 * m - n - 1) / 3)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int mod = 100000007;
    long long n, m, inv3;
    
    int ksm(int x, int y) {
    	int res = 1;
    	for( ; y ; y >>= 1, x = 1ll * x * x % mod) if(y & 1) res = 1ll * res * x % mod; return res;
    }
    
    int main() {
    
    	cin >> n >> m; inv3 = ksm(3, mod - 2);
    	if(n > m) swap(n, m); 
    	printf("%d", (n % mod * m % mod * (n - 1 + m - 1) % mod + 2 * n * (n - 1) % mod * (3 * m - n - 1) % mod * inv3 % mod) % mod);
    	
    	return 0;
    }
    

  • 相关阅读:
    PHP之数据库操作(一)
    PHP之字符串操作
    Subline使用方法
    POST和GET的区别(面试回答)
    面试题(1)
    http协议
    JS 闭包(内存溢出与内存泄漏)(垃圾回收机制)
    JS----事件机制 事件冒泡 事件捕获 事件委托
    js的数据类型、判断对象类型 js对象
    JS----DOM节点操作:创建 ,插入,删除,复制,查找节点
  • 原文地址:https://www.cnblogs.com/czhui666/p/13955732.html
Copyright © 2011-2022 走看看