res = [0 for i in range(4)]
n = int(input())
cnt , cnt1 = 0 , 0 # cnt1 记录报的个数
for i in range(1 , 200000):
if i % 7 == 0 or '7' in str(i):
res[cnt] += 1
else:
cnt1 += 1
if cnt1 == n:
break
cnt = (cnt + 1) % 4
for i in res:
print(i)
简单的图论问题
#include
#include
(让我想起高中时期的化学)
题目就是检查化学式是否配平,等式两边两个哈希表,哈希表中存储每一个元素的个数和这个元素本身。
使用递归求解可能有括号的化学式,角标相当于乘积。
#include
#include
#include
#include
#define x first
#define y second
using namespace std;
typedef unordered_map MPSI;
MPSI dfs(string &str , int &u)
{
MPSI res;
while(u < str.size())
{
if(str[u] == '(')
{
u ++; // 过滤掉'('
auto t = dfs(str , u);
u ++; // 过滤掉')'
int cnt = 1 , k = u;
// 计算角标
while(k < str.size() && isdigit(str[k])) k ++;
if(k > u)
{
cnt = stoi(str.substr(u , k - u));
u = k;
}
for(auto c : t)
res[c.x] += c.y * cnt;
}
else if(str[u] == ')') break;
else // 内部元素
{
int k = u + 1;
while(k < str.size() && str[k] >= 'a' && str[k] <= 'z') k ++;
auto key = str.substr(u , k - u);
u = k;
int cnt = 1;
while(k < str.size() && isdigit(str[k])) k ++;
if(k > u)
{
// 括号内部元素有角标
cnt = stoi(str.substr(u , k - u));
u = k;
}
res[key] += cnt;
}
}
return res;
}
MPSI work(string str)
{
MPSI res;
for(int i = 0;i < str.size();i ++)
{
int j = i + 1;
while(j < str.size() && str[j] != '+') j ++;
// 以+号分隔进行枚举
auto item = str.substr(i , j - i);
i = j;
int cnt = 1 , k = 0;
while(k < item.size() && isdigit(item[k])) k ++;
// 截取系数
if(k) cnt = stoi(item.substr(0 , k));
// 解析括号
auto t = dfs(item , k);
for(auto c : t)
res[c.x] += c.y * cnt;
}
return res;
}
int main()
{
int n;
cin >> n;
while(n --)
{
string s;
cin >> s;
int k = s.find("=");
auto left = work(s.substr(0 , k)) , right = work(s.substr(k + 1));
if(left == right) puts("Y");
else puts("N");
}
return 0;
}
首先使用邻接表存图,然后使用优先队列对于每一条查询数据进行排序
链表如何去存?
使用二维数组进行存储,对于需要更新的内容,我们将其拷贝到最后,使该节点指向这个链表,即可完成更改别的节点的同时不改变这个节点。
#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 510 , M = 2e4 + 10;
typedef vector VI;
int h[M] , ne[M] , e[M] , idx = 0;
int n , m , w , q;
vectorg; // 存储所有列表
int node[M]; // 链表的编号
void add(int a , int b)
{
e[idx] = b , ne[idx] = h[a] , h[a] = idx ++;
}
struct Op
{
// t时间 id编号 pid从哪个节点过来的 hid过来的链表的编号
int t , id , pid , hid;
// priority_queue默认大根堆,因此需要重载<
bool operator < (const Op &r) const
{
// 考虑什么情况当前元素要排到下一个元素的后面
return t > r.t;
}
};
priority_queue heap;
void eval()
{
auto t = heap.top();
heap.pop();
// a 堆顶元素对应的列表 b 新链表
auto &a = g[node[t.id]] , &b = g[t.hid];
if(b.size() > a.size() || b.size() == a.size() && b.back() < a.back())
{
// 当前链表id变为传回来的列表id
node[t.id] = t.hid;
for(int i = h[t.id];~i;i = ne[i])
if(e[i] != t.pid && e[i] != t.id)
heap.push({t.t + w , e[i] , t.id , t.hid});
}
}
int main()
{
cin >> n >> m;
g.push_back({0});
memset(h , -1 , sizeof h);
while(m --)
{
int a , b;
cin >> a >> b;
// scanf("%d %d" ,&a ,&b);
add(a , b) , add(b , a);
}
cin >> w >> q;
getchar();
while(q --)
{
string s;
getline(cin , s);
stringstream ss(s);
int a[3] , cnt = 0;
while(ss >> a[cnt]) cnt ++;
if(cnt == 3) // 添加块
{
// 当前有操作并且第一个操作时间小于当前的时间
while(heap.size() && heap.top().t <= a[1]) eval();
// 先复制当前链表
g.push_back(g[node[a[0]]]);
// 当前链表已经放置最后
g.back().push_back(a[2]);
// 当前链表已经在最后
node[a[0]] = g.size() - 1;
for(int i = h[a[0]];~i;i = ne[i])
if(e[i] != a[0]) // 判断自环
heap.push({a[1] + w , e[i] , a[0] , node[a[0]]});
}
else // 查询链表
{
// 进行完之前的所有操作
while(heap.size() && heap.top().t <= a[1]) eval();
cout << g[node[a[0]]].size() << " ";
for(auto x : g[node[a[0]]])
cout << x << " ";
cout << endl;
}
}
return 0;
}
n , q = map(int , input().split())
U = [314882150829468584 , 427197303358170108 , 1022292690726729920,
1698479428772363217, 2006101093849356424]
mod = 2009731336725594113
start = [i for i in range(n + 1)]
for _ in range(q):
l , r = map(int , input().split())
s = sum((start[i] % mod) % 2019 for i in range(l , r + 1))
print(s)
t = s % 5
for i in range(l , r + 1):
start[i] = start[i] % mod * U[t] % mod