2017年江西理工大学C语言程序设计竞赛(高级组)
问题 A: 求近似值
1 #include <stdio.h> 2 #include <time.h> 3 #include <stdlib.h> 4 using namespace std; 5 6 #define ll long long 7 const ll M = 9e18; 8 const ll MOD = 9932017; 9 struct Node { 10 ll m[2][2]; 11 }; 12 13 ll a[4966010]; 14 15 Node mul(Node a, Node b) { 16 Node A; 17 for(int i = 0; i < 2; ++i) { 18 for(int j = 0; j < 2; ++j) { 19 A.m[i][j] = 0; 20 for(int k = 0; k < 2; ++k) { 21 A.m[i][j] = (A.m[i][j] + a.m[i][k] * b.m[k][j] % MOD) % MOD; 22 } 23 } 24 } 25 return A; 26 } 27 28 ll q(Node a, ll num) { 29 Node AA; 30 AA.m[0][0] = AA.m[1][1] = 1; 31 AA.m[0][1] = AA.m[1][0] = 0; 32 while(num) { 33 if(num & 1) AA = mul(AA, a); 34 a = mul(a, a); 35 num >>= 1; 36 } 37 return 2LL * AA.m[0][0] - 1; 38 } 39 int main() { 40 ll n; 41 int t; 42 scanf("%d", &t); 43 while(t--) { 44 scanf("%lld", &n); 45 n %= 4966009; 46 if(n > 2483005) n = 2483005*2-n-1; 47 if(a[n]){ 48 printf("%lld\n", a[n]); 49 continue; 50 } 51 Node A; 52 A.m[0][0] = A.m[1][1] = 11; 53 A.m[1][0] = 60; 54 A.m[0][1] = 2; 55 //printf("%lld\n", q(A, n)); 56 a[n] = q(A, n); 57 printf("%lld\n", a[n]); 58 } 59 return 0; 60 }
超级模法师
- n % i = n - n / i * i (n / i 表示下取整)
- 所以所求 = n * m - sum(n/i * i) (i从1到m)
- 由于,n的第j个因子和第j+1个因子间(左开右闭),的任意数k,有n / k = n / n的第j+1个因子
- 所以我们用sqrt(n)的时间求出所有n的因子即可,然后相邻的两个用下等差数列求和公式很容易就能算出
- 求得过程有些坑点需要注意,首先是注意m的大小,m的大小可能位于n的两个因子之间
- 然后是,求和公式那里也需要先求下余,再算乘法,这样就需要注意因为有个除2,所以要判断用哪一项能整除2,除完后再求余
1 #include <iostream> 2 #include <stdio.h> 3 #include <cmath> 4 #define ll long long 5 using namespace std; 6 const int N = 1e7; 7 const ll mod = 1e9+7; 8 ll n , ans = 0 , m , a , b; 9 10 int main(){ 11 ll tmp = 500000004; 12 scanf("%lld%lld",&n,&m); 13 if(m > n){ 14 ans = ((m - n) % mod) * (n % mod) % mod; 15 m = n; 16 } 17 if(m <= N){ 18 for(int i = 1 ; i <= m ; i ++){ 19 ans += (n % i); 20 } 21 22 }else{ 23 for(int i = 1 ; ; i ++){ 24 ll x = n / i , y = n / (i + 1) + 1; 25 if(y > m){ 26 continue; 27 }else if(x >= m && y <= m){ 28 ans += (((n % m) + (n % y)) % mod) * ((((m - y + 1) % mod) * tmp) % mod) % mod; 29 30 }else{ 31 ans += (((n % x) + (n % y)) % mod) * ((((x - y + 1) % mod) * tmp) % mod) % mod; 32 } 33 if(y <= N){ 34 for(int k = 1 ; k < y ; k ++){ 35 ans += (n % k); 36 } 37 break; 38 } 39 } 40 } 41 printf("%lld\n",ans % mod); 42 }
Combinationaritilize
#include "stdio.h" #include "stdlib.h" int main(void) { int num; scanf("%d",&num); if(num&(num-1)) printf("no"); else printf("yes"); return 0; }
字符串最大表示
1 #include <iostream> 2 #include <stdio.h> 3 #include <cstring> 4 using namespace std; 5 int Next[1000005]; 6 char s[1000005]; 7 int main(){ 8 int T; 9 scanf("%d",&T); 10 while(T --){ 11 scanf("%s",s); 12 int tlen = strlen(s); 13 int j, k; 14 j = 0; k = -1; Next[0] = -1; 15 while(j < tlen){ 16 if(k == -1 || s[j] == s[k]) 17 Next[++j] = ++k; 18 else 19 k = Next[k]; 20 } 21 22 printf("%d\n",tlen / (tlen - Next[tlen])); 23 } 24 }
DATE ALIVE
二分图匹配,然后上模版
1 #include <iostream> 2 #include <time.h> 3 #include <stdio.h> 4 #include <vector> 5 #include <string.h> 6 using namespace std; 7 const int maxn = 509*2; 8 int n, x, y, sum; 9 bool vis[maxn]; 10 int use[maxn]; 11 vector<int> v[maxn]; 12 bool Find(int x){ 13 for(int i = 0; i < v[x].size(); ++i){ 14 int xx = v[x][i]; 15 if(!vis[xx]){ 16 vis[xx] = true; 17 if(!use[xx] || Find(use[xx])){ 18 use[xx] = x; 19 return true; 20 } 21 } 22 } 23 return false; 24 } 25 int main(){ 26 int n, m, k; 27 scanf("%d%d%d", &n, &m, &k); 28 for(int i = 0; i < k; ++i){ 29 scanf("%d%d", &x, &y); 30 v[x].push_back(y+501); 31 } 32 memset(use, 0, sizeof(use)); 33 for(int i = 1; i <= n; ++i){ 34 memset(vis, false, sizeof(vis)); 35 if(Find(i)) sum ++; 36 } 37 printf("%d\n", sum); 38 for(int i = 1; i <= x; ++i){ 39 v[i].clear(); 40 } 41 //printf("%.3lf\n", (double)clock()/CLOCKS_PER_SEC); 42 return 0; 43 }
敏感的小明
1 #include<bits/stdc++.h> 2 #include<stdio.h> 3 using namespace std; 4 int flag[15]; 5 int main(){ 6 memset(flag,0,sizeof(flag)); 7 int n; 8 cin>>n; 9 int num; 10 cin>>num; 11 for(int i=0;i<num;i++){ 12 int x; 13 cin>>x; 14 flag[x]=1; 15 } 16 for(int i=n;;i++){ 17 int j=i; 18 int fg=1; 19 if(flag[j%10]==1){ 20 fg=0; 21 }else{ 22 do{ 23 int y=j%10; 24 if(flag[y]==1){ 25 fg=0; 26 break; 27 } 28 j=j/10; 29 }while(j!=0); 30 } 31 if(fg==1){ 32 cout<<i<<endl; 33 break; 34 } 35 } 36 return 0; 37 }
初中数学
1 #include<iostream> 2 #include<stdio.h> 3 #include<bits/stdc++.h> 4 using namespace std; 5 int a[1050][1050]; 6 int main(){ 7 int n,m; 8 cin>>n>>m; 9 int cnt=0; 10 for(int i=1;i<n+1;i++){ 11 for(int j=1;j<m+1;j++){ 12 cin>>a[i][j]; 13 if(a[i][j]!=0){ 14 cnt+=2; 15 } 16 } 17 } 18 for(int i=1;i<n+1;i++){ 19 for(int j=1;j<m+1;j++){ 20 if(a[i][j]-a[i-1][j]>0){ 21 cnt+=a[i][j]-a[i-1][j]; 22 } 23 if(a[i][j]-a[i+1][j]>0){ 24 cnt+=a[i][j]-a[i+1][j]; 25 } 26 if(a[i][j]>a[i][j-1]) 27 cnt+=a[i][j]-a[i][j-1]; 28 if(a[i][j]>a[i][j+1]) 29 cnt+=a[i][j]-a[i][j+1]; 30 } 31 } 32 cout<<cnt<<endl; 33 34 }