#include<iostream>usingnamespace std;constint N =5010;int n;int f[N][N];int a[N];voidsolve(int x,int y){int t =1;for(int i =1; i <= y;++i)for(int j =0; i*j <= y;++j){if(x >= i && f[x-i][y-i*j]) t =0;elseif(x>=i*j && f[x-i*j][y-i]) t =0;}if(t) f[x][y]= f[y][x]= t;}intmain(){
f[0][0]= f[2][3]= f[3][2]=1;
n =5000;for(int i =3; i <= n;++i)for(int j = i; j <= n;++j){solve(i, j);if(f[i][j]){printf("p[%d]=%d\n", i, j);break;}}return0;}
B
题意
球掉进等腰梯形的框 问求能不能卡在框里
如果能输出球心到框底的高
思路
根据两次 相似三角形求答案
代码
#include<iostream>#include<cmath>usingnamespace std;constdouble eps =1e-8;double r, a, b, h;double ans;intmain(){
cin >> r >> a >> b >> h;if(2*r-b <0){printf("Drop\n");}else{double a1 =(a-b)/2;double b1 =sqrt(a1*a1+h*h)* r/h - b/2;
ans = h*b1/a1;printf("Stuck\n");printf("%.10lf", ans);}return0;}
D
题意
给一个01矩阵 一个字符串
1不能放 求字符串能放进01矩阵的方法数
思路
求每段0的长度 累加每段能放的方法数
代码
#include<iostream>#include<vector>usingnamespace std;typedeflonglong ll;constint N =2010;int n, m;
vector<int> q;
string s;intmain(){
cin >> n >> m;for(int i =0; i < n;++i){
cin >> s;int sum =0;for(int j =0; j < n;++j){if(s[j]=='0') sum++;elseif(sum) q.push_back(sum), sum =0;}if(sum) q.push_back(sum);}
cin >> s;
ll ans =0;for(int i =0; i < q.size();++i){int x = q[i];if(x >= m) ans += x-m+1;}
cout << ans << endl;return0;}
F
题意
求 [l, r] 区间内 能被3整除 或相邻的位数能被三整除
思路
能被三整除的数必定每一位相加是三的倍数
每次多一位数时必定会至少加1 如111 1+1+1 = 3
所以 当超过100时 必定有几个位数相加能被三整除
只要预处理100以内
求 1 到 r 和 1 到 l-1 再相减可得
代码
#include<iostream>usingnamespace std;typedeflonglong ll;typedeflongdouble ld;constint N =105;constint inf =0x3f3f3f3f;constint mod =1e9+7;int a[N];voidinit(){int ans =0;for(int i =1; i <=100;++i){int x = i/10, y = i%10;if(y%3==0) ans++;elseif(i>9&& x%3==0||(x+y)%3==0) ans++;
a[i]= ans;}}
ll dp(ll n){if(n<100)return a[n];return n-100+a[100];}intmain(){init();int t;scanf("%d",&t);while(t--){
ll l, r;scanf("%lld%lld",&l,&r);printf("%lld\n",dp(r)-dp(l-1));}return0;}
H
题意
给n个数 求一个最小的数
使得每个数 % 这个数都不相同
思路
用标记数组存这个值
从最小边界n 一直枚举 i 到最大边界r
需要优化
先排序然后二分找第一个大于等于 i 的数
如果存在失败跳出 不存在 标记成 i (偷个懒 因为i是递增的)
代码
#include<iostream>#include<algorithm>usingnamespace std;constint N =500010;int n;int a[N];int st[N];intsolve(int x){int l =0, r = n, mid;while(l <= r){
mid = l+r >>1;if(a[mid]< x) l = mid+1;else r = mid-1;}return r;}intmain(){scanf("%d",&n);for(int i =0; i < n;++i){scanf("%d",&a[i]);
st[a[i]]=-1;}sort(a, a+n);int l = n, r = a[n-1];int ans =max(n, r+1);for(int i = n; i <= r;++i){int m =solve(i);bool vis =1;for(int j = m; j < n;++j){int x = a[j]%i;if(st[x]==-1|| st[x]== i){
vis =0;break;}else st[x]= i;}if(vis){
ans = i;break;}}printf("%d\n", ans);return0;}
A题意Alice和Bob玩游戏 两堆石头从一堆中一堆拿a(a>0),另一堆拿a的整数倍(可为0)Alice先手 最优策略最后谁赢思路先暴力打表10分钟求出所有解 然后预处理代码#include<iostream>using namespace std;const int N = 5010;int n;int f[N][N];int a[N];void solve(int x, int y) { int t = 1; for(int i = 1;