结论:两个数a,b最大凑不出来的数是a*b-a-b(前提是gcd(a,b)==1);
codeforces C Chat Ban
一道二分的题目,由于二分没学过遗憾败北,其实这题目还是很简单的,只要二分找到第一个大于等于x的数的下标即可;
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
ll t,k,x;
ll cal(ll n){
if(n<=k) return n*(n+1)/2;
ll res=k*(k+1)/2;
n-=k;
res+=(k-1+k-n)*n/2;
return res;
}
int main(){
//freopen("in.txt","r",stdin);
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&k,&x);
ll l=0,r=2*k-1;
while(l+1<r){
ll mid=l+r>>1;
if(cal(mid)>=x) r=mid;
else l=mid;
}
cout<<r<<endl;
}
return 0;
}
codeforces E Eva and Euro coins
k个相同的字符是没有意义的,可以消掉,最后只要判断剩下的是否相等就可以了
2018 ICPC 南京 E. Eva and Euro coins(思维+栈)_Herod_的博客-CSDN博客
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
string resstring(string s,int k){
stack<int>num;//字符连续出现的次数
stack<char>st;//存储字符
for(int i=0;i<s.size();i++){
if(st.empty()||st.top()!=s[i]){
st.push(s[i]);
num.push(1);
}
else{
if(num.top()+1==k){//有k个字符连续了,删去
st.pop();
num.pop();
}
else{//还没到k个字符,记录一下
int tmp=num.top();
num.pop();
num.push(tmp+1);
}
}
}
string res="";
while(!st.empty()){
char ch=st.top();
st.pop();
int tmp=num.top();
num.pop();
for(int i=1;i<=tmp;i++)
res+=ch;
}
return res;
}
int main(){
//freopen("in.txt","r",stdin);
int n,k;
scanf("%d%d",&n,&k);
string str1,str2;
cin>>str1>>str2;
if(k==1)
printf("Yes\n");
else{
if(resstring(str1,k)==resstring(str2,k))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
求逆元的三个方法
codeforces G Pyramid
打表方法:定义一个坐标系,定义好所有点的坐标,然后暴力查看任意三个点是否能够成三角形
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
struct node{
double x,y;
}a[10001];
int cnt;
double dis(int i,int j){
return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
}
int judge(int i,int j,int k){
double a=dis(i,j);
double b=dis(j,k);
double c=dis(i,k);
if(fabs(a-b)<=0.001&&fabs(a-c)<=0.001&&fabs(b-c)<=0.001) return 1;
return 0;
}
int main(){
//freopen("in.txt","r",stdin);
for(int n=1;n<=20;n++){
cnt=0;
double posx=0;
double posy=0;
for(int i=n;i>=0;i--){
for(int j=0;j<=i;j++){
a[cnt].x=posx;
a[cnt++].y=posy+2*j;
}
posx+=sqrt(3);
posy+=1.0;
}
int ans=0;
for(int i=0;i<cnt;i++)
for(int j=i+1;j<cnt;j++)
for(int k=j+1;k<cnt;k++)
if(judge(i,j,k)==1)
ans++;
cout<<ans<<endl;
}
return 0;
}
【 数列做差性质 】G - Pyramid ( 打表 + 逆元 )_石旭先森的博客-CSDN博客
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
ll mod=1e9+7;
ll fpow(ll a,ll n){
ll ans=1;
while(n){
if(n&1) ans=(ans*a)%mod;
a=(a*a)%mod;
n>>=1;
}
return ans;
}
ll inv(int n){//费马小定理求逆元
return fpow(n,mod-2);
}
int main(){
//freopen("in.txt","r",stdin);
ll n,t;
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
long long ans=(fpow(n,4)%mod+fpow(n,3)*6%mod+fpow(n,2)*11%mod+n*6%mod)%mod;
ans=ans*inv(24)%mod;
ans%=mod;
printf("%lld\n",ans);
}
return 0;
}
luogu p3985
背包题,但体积很大,需要压缩,每个体积都减去体积的最小值minv,dp[j][k]代表选了j个物品的体积是多少,那么原来的体积就是j*minv+k,同时k最大只能取j的三倍(预处理完后每个v[i]就都是一个差值了,所以k的最大取值可以取到j*3,最大化k的范围),因为极差不能超过3,之后就在看成一个背包做就行,但极差那个地方的取值还是有些地方不大清楚。。。
【训练题8:(更新)大体积01背包变式】不开心的金明 | 洛谷 P3985_溢流眼泪的博客-CSDN博客
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
ll n,m,v[110],p[110],dp[110][10010];
int main(){
//freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
ll minv=inf;
for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&p[i]),minv=min(minv,v[i]);
for(int i=1;i<=n;i++) v[i]-=minv;
memset(dp,0,sizeof(dp));
ll ans=0;
for(ll i=1;i<=n;i++)
for(ll j=min(n,m/minv);j>=1;j--)
for(ll k=3*j;k>=v[i];k--){
if(j*minv+k<=m) dp[j][k]=max(dp[j][k],dp[j-1][k-v[i]]+p[i]);
ans=max(ans,dp[j][k]);
}
cout<<ans<<endl;
return 0;
}
codeforces nanjing2020 L Let's Play Curling
问题的实质就是看看哪一对b[j],b[j+1]容纳的a数组的个数最多,这个最多的个数就是答案;
codeforces E Evil Coordinate
统计字符串中L,R,U,D各自出现的个数,然后对L,R,U,D这四个字母进行全排列(因为无论怎么走影响路径的只有每个大方向(LRUD)的次序,大方向不同,所走的路径就不一样,所能避开的点也就不一样),每排列一次就模拟判断一次,如果到最后还没走到mx,my,就说明这条路径可行,输出即可,思路理解就好,代码有点过于丑陋;
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
ll t,mx,my;
char s[100005];
int main(){
//freopen("in.txt","r",stdin);
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&mx,&my);
scanf("%s",s);
int flag=0,len=strlen(s),l=0,r=0,u=0,d=0,flat=0;
ll x=0,y=0;
for(int i=0;i<len;i++){
if(s[i]=='L') l++;
if(s[i]=='R') r++;
if(s[i]=='U') u++;
if(s[i]=='D') d++;
}
if(mx==0&&my==0){
printf("Impossible\n");
continue;
}
char dir[5]={'D','L','R','U'};
while(next_permutation(dir,dir+4)){
x=0,y=0;
int flag=1;ll L=l,R=r,D=d,U=u;
for(int i=0;i<4;i++){
if(dir[i]=='L'){
while(L--){
x--;
if(x==mx&&y==my){
flag=0;break;
}
}
}
if(flag==0) break;
if(dir[i]=='R'){
while(R--){
x++;
if(x==mx&&y==my){
flag=0;break;
}
}
}
if(flag==0) break;
if(dir[i]=='U'){
while(U--){
y++;
//cout<<x<<" "<<y<<endl;
if(x==mx&&y==my){
//cout<<"YES"<<endl;
flag=0;
break;
}
}
}
if(flag==0) break;
if(dir[i]=='D'){
while(D--){
y--;
if(x==mx&&y==my){
flag=0;break;
}
}
}
if(flag==0) break;
}
if(flag){
flat=1;
for(int i=0;i<4;i++){
if(dir[i]=='L'){
while(l--){
printf("%c",'L');
}
}
if(dir[i]=='R'){
while(r--){
printf("%c",'R');
}
}
if(dir[i]=='U'){
while(u--){
printf("%c",'U');
}
}
if(dir[i]=='D'){
while(d--){
printf("%c",'D');
}
}
}
printf("\n");
break;
}
}
if(!flat) printf("Impossible\n");
}
return 0;
}