1001
这题是队友写的,结论挺好推的,直接放代码了。
#include<bits/stdc++.h>
using namespace std;
#define FOR(a,b,c) for(int a=b;a<=c;a++)
typedef long long ll;
typedef unsigned long long ull;
int mod =1e9+7;
int inf =(1<<31)-1;
ll ksm(int i,int j){
if(i==0)return 1;
ll ans=1;ll t=i;
while(j){
if(j&1)ans=ans*t%mod;
t=t*t%mod;
j>>=1;
}return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
ll n;
scanf("%lld",&n);
ll ans=0;
ll t=n/3;
while(t*3<n)
{
t++;
}
if(t%2==0)t++;
if(n%2==0)
ans=(n)/2+(n-t+1)/2;
else
ans=(n+1)/2+(n-t)/2+1;
printf("%lld\n",ans);
}
}
1006
这是一个构造题。
我们注意到对于任意的 i 都有(i+3)^ 2 - (i+2)^ 2 - (i+1)^ 2 + i^2=4,那么字符串“1001”就能产生4的贡献,所以当n%4=0时k个“1001”就能满足结果;当n%4=1时就构造“1”+k个“1001”;当n%4=2时就构造“0001”+k个“1001”;当n%4==3时就构造“01”+k个“1001”。(其中k=n/4向下取整)
附代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
int t;
cin >> t;
while (t--) {
int n;
scanf("%lld", &n);
if (n == 1) {
cout << 1 << endl << 1 << endl;
continue;
}
if (n == 2) {
cout << 4 << endl << "0001" << endl;
continue;
}
if (n == 3) {
cout << 2 << endl << "01" << endl;
continue;
}
int k = 0;
string ans;
if (n % 4 == 0) {
k = n;
for (int i = 1; i <= n / 4; i++) {
ans += "1001";
}
} else {
int cnt = n / 4, last;
last = n - cnt * 4;
if (last & 1) {
if (last == 1) {
ans += "1";
for (int i = 1; i <= cnt; i++) ans += "1001";
k = 1 + cnt * 4;
} else {
ans += "01";
for (int i = 1; i <= cnt; i++) ans += "1001";
k = 2 + cnt * 4;
}
} else {
ans += "0001";
for (int i = 1; i <= cnt; i++) ans += "1001";
k = cnt * 4 + 4;
}
}
cout << k << endl << ans << endl;
}
return 0;
}
1007
拿到题目首先想到要将g(x)进行处理,因为如果去掉g(x)原来的函数就是一个二次函数,二次函数的极值点很好求(要么在定义域的边界,要么在对称轴嘛)。注意到N的范围是(1<=N<=1e6),那么1<=g(x)<=54,可以预处理处对于任意的1<=x<=N的g(x)值,然后再找出距离对称轴最近的满足g(x)=i的x(i是x的数位和)。
附代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
vector<int> g[60];
void init() {
for (int i = 1; i <= 1000000; i++) {
int temp = i, sum = 0;
while (temp) {
sum += temp % 10;
temp /= 10;
}
g[sum].push_back(i);
}
}
int fx(int a, int b, int x) { return a * x * x + b * x; }
signed main() {
int t;
cin >> t;
for (int i = 1; i <= 54; i++) g[i].push_back(-1e9);
init();
for (int i = 1; i <= 54; i++) g[i].push_back(1e9);
while (t--) {
int a, b, c, d;
scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
int n;
scanf("%lld", &n);
int res = 1e18;
for (int x = 1; x <= 54; x++) {
if (g[x][1] > n) continue;
int l = 1,
r = --upper_bound(g[x].begin(), g[x].end(), n) - g[x].begin();
int A = a * x + b, B = c * x * x + d * x;
res = min({res, fx(A, B, g[x][l]), fx(A, B, g[x][r])});
//当A<=0时二次函数的极小值在定义域的两端取到,故不需要进行以下操作
if (A > 0) {
while (l <= r) {
int lmid = l + (r - l) / 3, rmid = r - (r - l) / 3;
int fl = fx(A, B, g[x][lmid]), fr = fx(A, B, g[x][rmid]);
if (fl <= fr)
r = rmid - 1;
else
l = lmid + 1;
res = min({res, fl, fr});
}
}
}
printf("%lld\n", res);
}
return 0;
}
1009
这题是我们队第一个ac的题,几乎是开题就有想法了。题意是说给了一个字符串,代表人行走的序列,问该字符串中有多少连续子串,使得人经过该子串的操作后能回到原点。首先进行所给字符串的操作得到一系列的坐标,其实答案就是对所有坐标中相等的坐标进行两两组合,比如(0,10)出现了10次,那么其对答案的贡献就是10*(10+1)/2。
附代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
struct node {
int x, y;
bool operator<(const node &a) const {
if (x != a.x)
return x < a.x;
else
return y < a.y;
}
};
map<node, int> mp;
signed main() {
int t;
cin >> t;
while (t--) {
int n;
scanf("%lld", &n);
string s;
cin >> s;
mp.clear();
int nowx = 0, nowy = 0;
node pos;
pos.x = nowx, pos.y = nowy;
mp[pos] = 1;
int ans = 0;
for (int i = 0; i < s.length(); i++) {
if (s[i] == 'U')
nowy++;
else if (s[i] == 'D')
nowy--;
else if (s[i] == 'L')
nowx--;
else
nowx++;
pos.x = nowx, pos.y = nowy;
if (!mp[pos])
mp[pos] = 1;
else
ans += mp[pos], mp[pos]++;
}
printf("%lld\n", ans);
}
return 0;
}
第一次写题解,如果有写得不好的地方请大家指出