思路:
记录所有因子出现的次数,如果有因子出现了两次及以上,说明可以 分解为整数的平方的整数倍。代码如下。
#include <cstdio>
#include <set>
#include<iostream>
#include<cmath>
#include <queue>
#include <utility>
#include <algorithm>
#include <map>
using namespace std;
int gcd(int x, int y)
{
int tmp;
if (x < y)
{
tmp = x;
x = y;
y = tmp;
}
while (y > 0)
{
tmp = x % y;
x = y;
y = tmp;
}
return x;
}
map<long long, long long >tt;
void check(long long a)
{
for (long long i = 2; i * i <= a; i++)
{
if(a%i==0)
{
tt[i]++;
tt[a / i]++;
}
}
}
int main()
{
bool flag = 0;
long long n,m,t;
cin >> n >> m;
if (n == m)
{
cout << "no credit"; return 0;
}
check(n), check(m);
for (auto it = tt.begin(); it != tt.end(); it++)
{
long long a = sqrt(it->first);
if (a * a == it->first || it->second > 1)
{
flag = 1;
break;
}
}
if (tt.size() == 0)
{
cout << "full credit";
}
else if (flag == 0 || n * m == 1)
{
cout << "partial credit";
}
else cout << "no credit";
return 0;
}
思路:从后向前,如果是相同的数,则将已有长度加一,可以继续;如果不同,则将已有长度乘二;代码如下
#include <cstdio>
#include <set>
#include<iostream>
#include<cmath>
#include <queue>
#include <utility>
#include <algorithm>
#include <map>
using namespace std;
int num[500005],n,t;
int main()
{
scanf("%d",&t);
for (int ii = 0; ii < t; ii++)
{
scanf("%d",&n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &num[i]);
}
int flag = num[n], ans = 0,cnt=1;
num[0] = flag;
for (int i = n; i >= 2; i--)
{
if (num[i] == flag && num[i - 1] != flag)
{
i -= cnt;
if(i>0)num[i] = flag;
cnt *= 2;
ans += 1;
i++;
}
else cnt++;
}
printf("%d\n",ans);
}
return 0;
}
用map装载不同数字出现的次数 ,然后遍历已经出现的数字,累加出现过数字的次数乘以比该数字 大c的数字;
#include <cstdio>
#include <set>
#include<iostream>
#include<cmath>
#include <queue>
#include <utility>
#include <algorithm>
#include <map>
using namespace std;
int n;
long long c;
map<long long, long long>m;
int main()
{
scanf("%d%lld", &n, &c);
long long ans = 0;
long long tmp;
set<long long>s;
for (int ii = 0; ii < n; ii++)
{
scanf("%lld", &tmp);
m[tmp]++;
s.insert(tmp);
}
for (auto it = s.begin(); it != s.end(); it++)
{
long long cur = *it;
ans += m[cur] * m[cur + c];
}
printf("%d", ans);
return 0;
}
思路:把不同位数的数分为不同的区间,当位数为一或二时可以特判;
#include <cstdio>
#include <set>
#include<iostream>
#include<cmath>
#include <queue>
#include <utility>
#include <algorithm>
#include <map>
using namespace std;
long long mod = 998244353;
int main()
{
unsigned long long n, mul = 10, ans = 0;
cin>>n;
while (1)
{
if (n == 10 && mul == 10)
{
ans = 46;
break;
}
else if (n <= 10 && mul == 10)
{
ans += (n + 1) * n / 2;
break;
}
else if (n > 10 && mul == 10)
{
ans += 45;
}
else if (n > mul&&mul!=10)
{
unsigned long long x = (mul - mul / 10) % mod;
unsigned long long y = (mul+1 - mul / 10) % mod;
ans += (x * y) / 2 % mod;
}
else if (n < mul&&mul!=10)
{
unsigned long long x = (n+1 - mul / 10) % mod;
unsigned long long y = (n + 2 - mul / 10) % mod;
ans += (x * y) / 2 % mod;
break;
}
mul *= 10;
}
cout << ans % mod << endl;
return 0;
}
思路:由于交换相邻的两个大臣不会对之前和之后的结果造成影响;
#include <cstdio>
#include <set>
#include<iostream>
#include<cmath>
#include <queue>
#include <utility>
#include <algorithm>
#include <map>
using namespace std;
int n, m, t;
int mod = 1000000007;
struct pep
{
unsigned long long a, b;
};
bool cp(pep a, pep b)
{
return (a.b * (b.a - 1) > b.b * (a.a - 1));
}
int main()
{
scanf("%d", &n);
pep p[1000005];
for (int i = 0; i<n; i++)
{
scanf("%lld%lld", &p[i].a, &p[i].b);
}
sort(p, p + n, cp);
unsigned long long mul[1000005];
mul[n - 1] = 1;
for (int i = n - 2; i >= 0; i--)
{
mul[i] = mul[i + 1] * p[i+1].a % mod;
}
unsigned long long ans = 0;
for (int i = 0; i < n; i++)
{
ans += p[i].b * mul[i] % mod;
ans% mod;
}
printf("%lld", ans % mod);
return 0;
}
运用到了快速求幂的技巧和离散数学中逆元的思想。
#include <cstdio>
#include <set>
#include<iostream>
#include<cmath>
#include <queue>
#include <utility>
#include <algorithm>
#include <map>
#include<stack>
using namespace std;
#define mode 1000000007
#define ll long long
#define N 1000005
ll qpow(ll a, ll n)
{
ll ans = 1;
while (n)
{
if (n & 1)
{
ans = ans * a % 1000000007;
}
a = a * a % 1000000007;
n >>= 1;
}
return ans;
}
ll a, b, m, ans = 0;
ll f[N],nif[N];
ll c(ll a, ll b)
{
return (f[a] * nif[b] %mode * nif[a - b] % mode) % mode;
}
int main()
{
cin >> a >> b >> m;
f[0] = 1, nif[0] = 1;
ll ans = 0;
for (ll i = 1; i < N; i++)
{
f[i] = i * f[i - 1] % mode;
}
nif[N - 1] = qpow(f[N - 1], mode - 2);
for (ll i = N - 2; i >= 1; i--)
{
nif[i] = nif[i + 1] * (i + 1) % mode;
}
for (ll i = 0; i <= m; i++)
{
ll cnt = i * a + (m - i) * b;
bool flag = 0;
while (cnt)
{
if (cnt % 10 != a && cnt % 10 != b)
{
flag = 1; break;
}
cnt /= 10;
}
if (flag == 0)ans = (ans + c(m, i)) % mode;
}
cout << ans % mode;
return 0;
}
二分查找,但是由于有向上取整,所以精度要求较高,需要用double型进行判断,如果最后结果与强转为int型后的差值大于一个值,则可以认为需要进一;
#include <cstdio>
#include <set>
#include<iostream>
#include<cmath>
#include <queue>
#include <utility>
#include <algorithm>
#include <map>
#include<stack>
using namespace std;
#define mode 1000000007
#define ll long long
#define N 1000005
ll qpow(ll a, ll n)
{
ll ans = 1;
while (n)
{
if (n & 1)
{
ans = ans * a % 1000000007;
}
a = a * a % 1000000007;
n >>= 1;
}
return ans;
}
int h[N];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> h[i];
}
double l = 0, r = 100000000;
double mid,e;
bool fu = 0;
while (l <= r)
{
fu = 0;
mid = (l + r) / 2;
e = mid;
for (int i = 1; i <= n; i++)
{
e += e - h[i];
if (e < 0)
{
fu = 1; break;
}
}
if (fu == 1)
{
l = mid + 0.005;
}
else
{
r = mid - 0.005;
}
}
if (mid - int(mid) > 0.01)mid += 1;
cout << (int)mid;
return 0;
}
简单的bfs捏。先把所i有可以到达的点都预处理一遍,最后统一输出即可。
#include <cstdio>
#include <set>
#include<iostream>
#include<cmath>
#include <queue>
#include <utility>
#include <algorithm>
#include <map>
#include<stack>
using namespace std;
#define mode 1000000007
#define ll long long
#define maxn 100000
#define N 100005
ll qpow(ll a, ll n)
{
ll ans = 1;
while (n)
{
if (n & 1)
{
ans = ans * a % 1000000007;
}
a = a * a % 1000000007;
n >>= 1;
}
return ans;
}
int b[N],ans[N];
int a, q;
int vis[100005] = {0};
queue<int> que;
void bfs(int cur)
{
que.push(cur);
int tmp;
while (!que.empty())
{
tmp = que.front();
que.pop();
if (tmp + 1 <= maxn&&!vis[tmp+1])
{
vis[tmp + 1] = vis[tmp] + 1;
que.push(tmp + 1);
}
if (tmp - 1 >= 0 && !vis[tmp - 1])
{
vis[tmp - 1] = vis[tmp] + 1;
que.push(tmp - 1);
}
if (tmp * 2 <= maxn && !vis[tmp * 2])
{
vis[tmp *2] = vis[tmp] + 1;
que.push(tmp *2);
}
if (tmp *3 <= maxn && !vis[tmp *3])
{
vis[tmp *3] = vis[tmp] + 1;
que.push(tmp *3);
}
}
}
int main()
{
cin >> a >> q;
for (int i = 0; i < q; i++)
{
cin >> b[i];
}
vis[a] = 1;
bfs(a);
for (int i = 0; i < q; i++)
{
cout << vis[b[i]]-1;
if (i < q - 1)cout << ' ';
}
return 0;
}