A.张老师和菜哭武的游戏
Solution
容易知道:
可以利用上式构造出任意的点,故计算能走到点的个数即可。
求和的最大公约数就行了,我们所能构造的最小的,个数为。
如果你不知道为什么求最大公约数就行了,可以看下文更相损减术(转载自百度文库):
更相减损术
《九章算术》是中国古代的数学专著,其中的“更相减损术”可以用来求两个数的最大公约数,即“可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。”
翻译成现代语言如下:
第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。
其中所说的“等数”,就是最大公约数。求“等数”的办法是“更相减损”法。
Code
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int>P; const double eps = 1e-8; const int NINF = 0xc0c0c0c0; const int INF = 0x3f3f3f3f; const ll mod = 1e9 + 7; const ll maxn = 1e6 + 5; ll gcd(ll a,ll b) {return b==0?a:gcd(b,a%b); } void solve(){ ll n,a,b; cin>>n>>a>>b; int temp=gcd(a,b); int ans=n/temp; if(ans&1) cout<<"Yes\n"; else cout<<"No\n"; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int T;cin>>T; while(T--){ solve(); } return 0; }
B.伤害计算
Solution
按照题目意思模拟就行了。
坑点:没注意输出结尾要求需要判断一下。
Code
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int>P; const double eps = 1e-8; const int NINF = 0xc0c0c0c0; const int INF = 0x3f3f3f3f; const ll mod = 1e9 + 7; const ll maxn = 1e6 + 5; const int N = 1e5 + 5; char s[N]; double solve(int x) {return (1+x)/2.0;} int main(){ cin>>s+1; int n=strlen(s+1); double ans=0; int j=0; int k=0; for(int i=1;i<=n;i++){ while(isdigit(s[i]) && i<=n){ j=j*10+(s[i]-'0'); i++; } if(s[i]=='d'){ i++; while(isdigit(s[i]) && i<=n){ k=k*10+(s[i]-'0'); i++; } ans+=j*solve(k); j=k=0; }else{ ans+=j; j=0; } } if(fmod(ans,1)<=eps) printf("%lld\n",(ll)ans); else printf("%.1f\n",ans); return 0; }
D.车辆调度
Solution
注意题目的数据范围极小,故可以直接搜索,我写了个DFS,本来按道理是应该1A的,但是比赛的时候数据有问题一直卡在90.91,赛后重测果然本来应该是1A的,后面还陆续改了一个小时想着debug啥的,也找不出啥,下次还是考虑过了一定时间就换题吧。
Code
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int>P; const double eps = 1e-8; const int NINF = 0xc0c0c0c0; const int INF = 0x3f3f3f3f; const ll mod = 1e9 + 7; const ll maxn = 1e6 + 5; const int N = 10 + 5; int n,m,K,cnt; char s[N][N]; int dx[4]={1,-1,0,0}; int dy[4]={0,0,1,-1}; bool book[N][N]; vector<pair<int,int> >V; void dfs(int x,int y,int cnt){ if(book[x][y] && cnt==K){ cout<<"YES\n"; exit(0); } if(cnt>=K) return; for(int i=0;i<V.size();i++){ for(int j=0;j<4;j++){ int x=V[i].first,y=V[i].second; int tx=x,ty=y; while(s[tx+dx[j]][ty+dy[j]]=='.') tx+=dx[j],ty+=dy[j]; swap(s[tx][ty],s[x][y]); V[i].first=tx,V[i].second=ty; dfs(tx,ty,cnt+1); V[i].first=x,V[i].second=y; swap(s[tx][ty],s[x][y]); } } } int main(){ ios::sync_with_stdio(false); cin.tie(0); cin>>m>>n>>K; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>s[i][j]; if(s[i][j]=='R') V.push_back({i,j}); if(s[i][j]=='D') {s[i][j]='.',book[i][j]=true;} } } dfs(0,0,0); cout<<"NO\n"; return 0; }
E.弦
Solution
前置知识:卡特兰数。
首先要能看出来这个的圆上连线且不相交的情况为卡特兰数。
卡特兰数常用的递推公式:
然后答案就是
接着就是求连线的方法数了,这是排列组合,,代表排列为一排的个数,代表两个为一组的重复情况,代表不同组数的排列情况。
Code
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int>P; const double eps = 1e-8; const int NINF = 0xc0c0c0c0; const int INF = 0x3f3f3f3f; const ll mod = 1e9 + 7; const ll maxn = 1e6 + 5; ll qpow(ll a,ll b){ ll ans=1; while(b>0){ if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; } int main(){ ios::sync_with_stdio(false); cin.tie(0); ll n;cin>>n; ll ans=1; for(int i=2;i<=n+1;i++) ans=ans*i%mod; cout<<qpow(2,n)*qpow(ans,mod-2)%mod<<'\n'; return 0; }
F.排列计算
Solution
差分裸题,贪心只有出现次数越多的点填的数字越大,才能满足最优解。
Code
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int>P; const double eps = 1e-8; const int NINF = 0xc0c0c0c0; const int INF = 0x3f3f3f3f; const ll mod = 1e9 + 7; const ll maxn = 1e6 + 5; const int N = 2e5 + 5; ll n,m; ll d[N]; int main(){ ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m; for(ll i=1;i<=m;i++){ ll l,r;cin>>l>>r; d[l]++,d[r+1]--; } for(ll i=1;i<=n;i++){ d[i]+=d[i-1]; } sort(d+1,d+1+n); ll ans=0; for(ll i=1;i<=n;i++){ ans+=d[i]*i; } cout<<ans<<'\n'; return 0; }