A:
求B对P的逆元就好了www
#include <iostream>
#include <cstdio>
#define int long long
const int mod=9973;
int inv,p,s;
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
int ans=exgcd(b,a%b,x,y);
int tmp=x;
x=y;
y=tmp-a/b*y;
return ans;
}
void work()
{
int n,b;
scanf("%lld%lld",&n,&b);
exgcd(b,mod,inv,s);
inv=(inv+mod)%mod;
printf("%lld\n",(inv*n)%mod);
}
signed main()
{
int T;
scanf("%lld",&T);
while(T--) work();
return 0;
}
B:
存前三位后三位然后快速幂就完事了
#include <iostream>
#include <cstdio>
#define il inline
il double devs(double x)
{
while(x>=1000.0) x/=10;
return x;
}
il int ksm1(int x,int y)
{
x%=1000;
int ans=1;
while(y)
{
if(y%2) ans=(ans*x)%1000;
x=(x*x)%1000;
y/=2;
}
return ans;
}
il int ksm2(double x,int y)
{
x=devs(x);
double ans=1;
while(y)
{
if(y%2) ans=devs(ans*x);
x=devs(x*x);
y/=2;
}
return (int)devs(ans);
}
int main()
{
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
int n,k;
scanf("%d%d",&n,&k);
printf("Case %d: %d %03d\n",i,ksm2((double)n,k),ksm1(n,k));
}
return 0;
}
C:
设最小步数为t
那么 (x+tm)%L=(y+tn)%L
那么 t*(m-n)≡(y-x)modL 然后
(
m
−
n
)
∗
t
+
k
∗
L
=
y
−
x
(m-n)*t+k*L=y-x
(m−n)∗t+k∗L=y−x
然后套个拓欧解方程…
#include <cstdio>
#define ll long long
ll x,y,m,n,a,b,c,l;
ll e_gcd(ll a,ll b)
{
if(!b)
{
x=1;
y=0;
return a;
}
ll ans=e_gcd(b,a%b);
ll tmp=x;
x=y;
y=tmp-a/b*y;
return ans;
}
int main()
{
scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);
a=m-n;b=l;c=y-x;
if(a<0) a=-a,c=-c;
ll g=e_gcd(a,b);
if(c%g) printf("Impossible\n");
else printf("%lld\n",(c/g*x%(b/g)+b/g)%(b/g));
return 0;
}
D:
这…模拟一下就过了
#include <iostream>
#include <cstdio>
int f1,f2,n;
int work()
{
int ans=2;
while(1)
{
int t=f1+f2;
f1=f2;
f2=t;
if(f2<=n) ans++;
else break;
}
return ans;
}
int main()
{
while((scanf("%d%d%d",&f1,&f2,&n))!=EOF) printf("%d\n",work());
return 0;
}
E:
首先因为X,Y不能相同,所以每个木块只有可能有6个放法,把他们都搞出来,存起来,然后大的在下Dp就好了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxm=100;
struct node{
int x,y,z;
}h[maxm*6];
int maxh[maxm*6];
int n;
int ts=0;
bool comp(node x1,node x2)
{
if(x1.x==x2.x) return x1.y>x2.y;
return x1.x>x2.x;
}
void work()
{
int ans=-1;
memset(h,0,sizeof(h));
memset(maxh,0,sizeof(maxh));
int tot=0;
for(int i=1;i<=n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
h[++tot].x=a,h[tot].y=b,h[tot].z=c;
h[++tot].x=a,h[tot].y=c,h[tot].z=b;
h[++tot].x=b,h[tot].y=a,h[tot].z=c;
h[++tot].x=b,h[tot].y=c,h[tot].z=a;
h[++tot].x=c,h[tot].y=a,h[tot].z=b;
h[++tot].x=c,h[tot].y=b,h[tot].z=a;
}
std::sort(h+1,h+tot+1,comp);
for(int i=1;i<=tot;i++) maxh[i]=h[i].z;
for(int i=2;i<=tot;i++)
{
int plus=0;
for(int j=1;j<i;j++)
if(maxh[j]>plus)
if((h[j].x>h[i].x)&&(h[j].y>h[i].y)) plus=maxh[j];
maxh[i]+=plus;
ans=std::max(ans,maxh[i]);
}
printf("Case %d: maximum height = %d\n",ts,ans);
}
int main()
{
while(1)
{
scanf("%d",&n);
if(!n) return 0;
ts++;
work();
}
}
F:
dp[l][r]表示把 l-r这些断点都砍断最低代价是多少
然后记忆化搜索就行了
#include <cstdio>
#include <iostream>
#include <cstring>
const int inf=1e9+7;
int dp[55][55];
int a[55];
int len,n;
int dfs(int l,int r)
{
if(~dp[l][r]) return dp[l][r];
if(l>=(r-1)) return dp[l][r]=0;
dp[l][r]=inf;
for(int i=l+1;i<r;i++) dp[l][r]=std::min(dp[l][r],dfs(l,i)+dfs(i,r)+a[r]-a[l]);
return dp[l][r];
}
int main()
{
while(1)
{
scanf("%d",&len);
if(!len) return 0;
scanf("%d",&n);
memset(dp,-1,sizeof(dp));
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
a[n+1]=len;
printf("The minimum cutting is %d.\n",dfs(0,n+1));
}
return 0;
}
G:
完全背包+二进制优化…
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
const int maxm=200005;
int s[7];
bool dp[maxm];
int w[maxm];
bool work()
{
memset(dp,0,sizeof(dp));
int p=0;
for(int i=1;i<=6;i++) p+=s[i]*i;
if(p%2) return 0;
p/=2;
dp[0]=1;
int cnt=0;
for(int i=1;i<=6;i++)
{
for(int j=1;j<=s[i];j*=2) w[++cnt]=j*i,s[i]-=j;
if(s[i]>0) w[++cnt]=i*s[i];
}
for(int i=1;i<=cnt;i++)
for(int j=p;j>=w[i];j--)
if(dp[j-w[i]]) dp[j]=1;
return dp[p];
}
int main()
{
int t=0;
while(1)
{
bool flag=0;
for(int i=1;i<=6;i++)
{
scanf("%d",&s[i]);
if(s[i]) flag=1;
}
if(!flag) return 0;
t++;
if(!work()) printf("Collection #%d:\nCan't be divided.\n\n",t);
else printf("Collection #%d:\nCan be divided.\n\n",t);
}
}
H:
dp[i]表示高度为i的方案数,然后递推就好了,感觉有点背包的意思,别忘了去掉全是高度为1的情况
#include <cstdio>
#include <iostream>
#include <cstring>
#define int long long
int dp[600];
signed main()
{
int n;
while(scanf("%lld",&n)&&n)
{
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=1;i<=n;i++)
for(int j=n;j>=i;j--)
dp[j]+=dp[j-i];
printf("%lld\n",dp[n]-1);
}
return 0;
}
I:
记忆化搜索…
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
int t[105][105],x2,y2,maxf=-1,f[105][105];
int dx[5]={0,1,-1,0,0},dy[5]={0,0,0,-1,1};
int dfs(int x,int y)
{
for(int i=1;i<=4;i++)
{
int x3,y3;
x3=x+dx[i];
y3=y+dy[i];
if(x3>=1&&x3<=x2&&y3>=1&&y3<=y2)
{
if(t[x][y]>=t[x3][y3]) continue;
if(f[x3][y3]!=1) f[x][y]=max(f[x][y],f[x3][y3]+1);
else f[x][y]=max(f[x][y],dfs(x3,y3)+1);
}
}
return f[x][y];
}
int main()
{
scanf("%d%d",&x2,&y2);
for(int i=1;i<=x2;i++)
for(int j=1;j<=y2;j++)
{
scanf("%d",&t[i][j]);
f[i][j]=1;
}
for(int i=1;i<=x2;i++)
for(int j=1;j<=y2;j++)
{
if(f[i][j]!=1) maxf=max(maxf,f[i][j]);
else maxf=max(maxf,dfs(i,j));
}
printf("%d",maxf);
return 0;
}
J:
区间dp
dp[i][j]表示i-j的最大匹配数
枚举i,j
如果i,j匹配,那么dp[i][j]=dp[i+1][j-1]+2
考虑不匹配 dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j])
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
const int maxm=1e5+100;
char s[maxm];
int dp[105][105];
bool ok(int x,int y){return (s[x]=='('&&s[y]==')')||(s[x]=='['&&s[y]==']');}
inline void work()
{
memset(dp,0,sizeof(dp));
int n=strlen(s+1);
for(int i=n;i>=1;i--)
for(int j=i+1;j<=n;j++)
{
if(ok(i,j)) dp[i][j]=dp[i+1][j-1]+2;
for(int k=i;k<=j-1;k++) dp[i][j]=std::max(dp[i][j],dp[i][k]+dp[k+1][j]);
}
printf("%d\n",dp[1][n]);
}
int main()
{
while(scanf("%s",(s+1))&&s[1]!='e') work();
return 0;
}