没什么。。。。

用 h 表明当前余数 即现阶段被除数
如果 h < b 需要补位 最后一位无数可补
最后需要去掉数字前面的0 但要考虑到商本身就是0的情况

#include
using namespace std;
int a[100005];
int ans[100005];
int main(){
long long b;
string aa;
cin>>aa>>b;
int n=aa.length();
for(int i=0;i<n;i++){
a[i]=aa[i]-‘0’;
}
long long h=a[0];
int i=0;
while(i<n){
if(h<b){
if(i==n-1)
break;
h*=10;
h+=a[++i];
}
ans[i]=h/b;
h%=b;
}
int pd=1;
for(int i=0;i<n;i++){
if(pd&&ans[i]0){
continue;
}else if(ans[i]!=0){
pd=0;
}
cout<<ans[i];
}
if(pd
1)
cout<<0;
cout<<endl;
cout<<h;
return 0;
}

题目描述
给定两个非负整数(不含前导 00) AA,BB,请你计算 A/BA/B 的商和余数。

输入格式
共两行,第一行包含整数 AA,第二行包含整数 BB。

输出格式
共两行,第一行输出所求的商,第二行输出所求余数。

数据范围
1≤A的长度≤1000001≤A的长度≤100000,
1≤B≤100001≤B≤10000,
BB 一定不为 0

输入样例:
7
2
输出样例:
3
1
算法1
(高精度) O(n2)O(n2)
高精度除法要求求出商和余数,那我们的思路就是:把上一次的余数乘10,再加上当前位上的数,就是被除数,后面往C(答案)里压入这个数字除以bb,就可以得到商在这个位置上的数字。

时间复杂度
参考文献
C++ 代码
#include
#include
#include
using namespace std;
vector div(vector &A,int b,int &r){ // 取r的地址符,是为了更改r的值,方便后面输出余数
vector C; // 答案
r = 0; // 余数
for(int i = A.size() - 1;i >= 0;i --){ // 从最高位开始处理
r = r * 10 + A[i]; // 上一次的余数乘10,再加上当前位上的数,就是被除数
C.push_back(r / b); // 往C里压入这个被除数除b
r %= b; // 计算余数
}
reverse(C.begin(),C.end()); // 因为除法运算中从高位开始计算,而前导0都在顶部而不是底部,所以要翻转过来
while (C.size() > 1 && C.back() == 0) C.pop_back(); // 去除前导0
return C; // 返回答案
}
int main(){
string a;
int b;
cin>>a>>b;
vector A;
for(int i = a.size() - 1;i >= 0;i --) A.push_back(a[i] - ‘0’); // 倒序
int r;
auto C = div(A,b,r); // 答案
for(int i = C.size() - 1;i >= 0;i --) cout<<C[i];
cout<<endl<<r<<endl;
return 0;
}

3

mex函数
将图上一个点可以到达的所有点的mex值组成一个集合

集合中不存在的最小自然数

此题用到的图
将终点状态(所有无法继续操作的石子数)的mex值设为0

起点为其中一堆石子的石子数

通过每种石子数可以到达的状态算出起点的mex值

就像这样:(样例的第3堆石子)

它的mex值就是:

所以mex(7)=0

必胜态和必败态
(这里只考虑一幅图)

当这幅图的起点的mex值为0

就是必败态

否则就是必胜态

原因:

从mex值的定义可以看出

当一个点的mex值为0

它一定只能到达mex值不为0的点

当一个点的mex值不为0

它一定可以到达mex值为0的点(双方都绝顶聪明,所以一定会到达mex值为0的点)

这时因为所有终点的mex值都是0

所以起点的mex值为零

说明先手一定走不到终点

所以是必败态

否则先手一定会走到终点

就是必胜态

解题方法
把n堆石子作为n幅图的起始点

每一步只能选择一幅图走一步

一个点的mex值为x

说明它可以到达mex值为0~x-1中任意一个自然数的点

所以可以从起点的mex值中拿取任意数值

有n个起点

这不就是经典nim游戏吗?!

所以把所有图起点的mex值亦或起来,就是结果

C++ 代码
#include
#include
#include<unordered_set>
using namespace std;
int f[10005],s[105],k,n;
int sg(int x){ //用来求mex值
if(f[x]!=-1) //记忆化搜索,可以优化掉不少
return f[x];
unordered_set vis; //用来记录所有可以到达的点的mex值
for(int i=0;i<k;i++)
if(x>=s[i]) //可以这么拿
vis.insert(sg(x-s[i]));
for(int i=0;;i++)
if(!vis.count(i))
return f[x]=i; //求出x点的mex值
}
int main(){
memset(f,-1,sizeof f);
scanf(“%d”,&k);
for(int i=0;i<k;i++)
scanf(“%d”,&s[i]);
scanf(“%d”,&n);
int ans=0;
while(n–){
int now;
scanf(“%d”,&now);
ans^=sg(now);
}
puts(ans?“Yes”:“No”);
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值